// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_BIND_H_ #define BASE_BIND_H_ #include #include #include #include #include "base/bind_internal.h" #include "base/compiler_specific.h" #include "base/template_util.h" #include "build/build_config.h" #if defined(OS_MACOSX) && !HAS_FEATURE(objc_arc) #include "base/mac/scoped_block.h" #endif // ----------------------------------------------------------------------------- // Usage documentation // ----------------------------------------------------------------------------- // // Overview: // base::BindOnce() and base::BindRepeating() are helpers for creating // base::OnceCallback and base::RepeatingCallback objects respectively. // // For a runnable object of n-arity, the base::Bind*() family allows partial // application of the first m arguments. The remaining n - m arguments must be // passed when invoking the callback with Run(). // // // The first argument is bound at callback creation; the remaining // // two must be passed when calling Run() on the callback object. // base::OnceCallback cb = base::BindOnce( // [](short x, int y, long z) { return x * y * z; }, 42); // // When binding to a method, the receiver object must also be specified at // callback creation time. When Run() is invoked, the method will be invoked on // the specified receiver object. // // class C : public base::RefCounted { void F(); }; // auto instance = base::MakeRefCounted(); // auto cb = base::BindOnce(&C::F, instance); // std::move(cb).Run(); // Identical to instance->F() // // base::Bind is currently a type alias for base::BindRepeating(). In the // future, we expect to flip this to default to base::BindOnce(). // // See //docs/callback.md for the full documentation. // // ----------------------------------------------------------------------------- // Implementation notes // ----------------------------------------------------------------------------- // // If you're reading the implementation, before proceeding further, you should // read the top comment of base/bind_internal.h for a definition of common // terms and concepts. namespace base { namespace internal { // IsOnceCallback is a std::true_type if |T| is a OnceCallback. template struct IsOnceCallback : std::false_type {}; template struct IsOnceCallback> : std::true_type {}; // Helper to assert that parameter |i| of type |Arg| can be bound, which means: // - |Arg| can be retained internally as |Storage|. // - |Arg| can be forwarded as |Unwrapped| to |Param|. template struct AssertConstructible { private: static constexpr bool param_is_forwardable = std::is_constructible::value; // Unlike the check for binding into storage below, the check for // forwardability drops the const qualifier for repeating callbacks. This is // to try to catch instances where std::move()--which forwards as a const // reference with repeating callbacks--is used instead of base::Passed(). static_assert( param_is_forwardable || !std::is_constructible&&>::value, "Bound argument |i| is move-only but will be forwarded by copy. " "Ensure |Arg| is bound using base::Passed(), not std::move()."); static_assert( param_is_forwardable, "Bound argument |i| of type |Arg| cannot be forwarded as " "|Unwrapped| to the bound functor, which declares it as |Param|."); static constexpr bool arg_is_storable = std::is_constructible::value; static_assert(arg_is_storable || !std::is_constructible&&>::value, "Bound argument |i| is move-only but will be bound by copy. " "Ensure |Arg| is mutable and bound using std::move()."); static_assert(arg_is_storable, "Bound argument |i| of type |Arg| cannot be converted and " "bound as |Storage|."); }; // Takes three same-length TypeLists, and applies AssertConstructible for each // triples. template struct AssertBindArgsValidity; template struct AssertBindArgsValidity, TypeList, TypeList, TypeList> : AssertConstructible, Unwrapped, Params>... { static constexpr bool ok = true; }; // The implementation of TransformToUnwrappedType below. template struct TransformToUnwrappedTypeImpl; template struct TransformToUnwrappedTypeImpl { using StoredType = std::decay_t; using ForwardType = StoredType&&; using Unwrapped = decltype(Unwrap(std::declval())); }; template struct TransformToUnwrappedTypeImpl { using StoredType = std::decay_t; using ForwardType = const StoredType&; using Unwrapped = decltype(Unwrap(std::declval())); }; // Transform |T| into `Unwrapped` type, which is passed to the target function. // Example: // In is_once == true case, // `int&&` -> `int&&`, // `const int&` -> `int&&`, // `OwnedWrapper&` -> `int*&&`. // In is_once == false case, // `int&&` -> `const int&`, // `const int&` -> `const int&`, // `OwnedWrapper&` -> `int* const &`. template using TransformToUnwrappedType = typename TransformToUnwrappedTypeImpl::Unwrapped; // Transforms |Args| into `Unwrapped` types, and packs them into a TypeList. // If |is_method| is true, tries to dereference the first argument to support // smart pointers. template struct MakeUnwrappedTypeListImpl { using Type = TypeList...>; }; // Performs special handling for this pointers. // Example: // int* -> int*, // std::unique_ptr -> int*. template struct MakeUnwrappedTypeListImpl { using UnwrappedReceiver = TransformToUnwrappedType; using Type = TypeList()), TransformToUnwrappedType...>; }; template using MakeUnwrappedTypeList = typename MakeUnwrappedTypeListImpl::Type; // Used below in BindImpl to determine whether to use Invoker::Run or // Invoker::RunOnce. // Note: Simply using `kIsOnce ? &Invoker::RunOnce : &Invoker::Run` does not // work, since the compiler needs to check whether both expressions are // well-formed. Using `Invoker::Run` with a OnceCallback triggers a // static_assert, which is why the ternary expression does not compile. // TODO(crbug.com/752720): Remove this indirection once we have `if constexpr`. template constexpr auto GetInvokeFunc(std::true_type) { return Invoker::RunOnce; } template constexpr auto GetInvokeFunc(std::false_type) { return Invoker::Run; } template