// 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_APPLE) && !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 {}; // Helpers to make error messages slightly more readable. template struct BindArgument { template struct ForwardedAs { template struct ToParamWithType { static constexpr bool kCanBeForwardedToBoundFunctor = std::is_constructible::value; // Note that this intentionally drops the const qualifier from // `ForwardingType`, to test if it *could* have been successfully // forwarded if `Passed()` had been used. static constexpr bool kMoveOnlyTypeMustUseBasePassed = kCanBeForwardedToBoundFunctor || !std::is_constructible&&>::value; }; }; template struct BoundAs { template struct StoredAs { static constexpr bool kBindArgumentCanBeCaptured = std::is_constructible::value; // Note that this intentionally drops the const qualifier from // `BoundAsType`, to test if it *could* have been successfully bound if // `std::move()` had been used. static constexpr bool kMoveOnlyTypeMustUseStdMove = kBindArgumentCanBeCaptured || !std::is_constructible&&>::value; }; }; }; // 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: // With `BindRepeating`, there are two decision points for how to handle a // move-only type: // // 1. Whether the move-only argument should be moved into the internal // `BindState`. Either `std::move()` or `Passed` is sufficient to trigger // move-only semantics. // 2. Whether or not the bound, move-only argument should be moved to the // bound functor when invoked. When the argument is bound with `Passed`, // invoking the callback will destructively move the bound, move-only // argument to the bound functor. In contrast, if the argument is bound // with `std::move()`, `RepeatingCallback` will attempt to call the bound // functor with a constant reference to the bound, move-only argument. This // will fail if the bound functor accepts that argument by value, since the // argument cannot be copied. It is this latter case that this // static_assert aims to catch. // // In contrast, `BindOnce()` only has one decision point. Once a move-only // type is captured by value into the internal `BindState`, the bound, // move-only argument will always be moved to the functor when invoked. // Failure to use std::move will simply fail the `kMoveOnlyTypeMustUseStdMove` // assert below instead. // // Note: `Passed()` is a legacy of supporting move-only types when repeating // callbacks were the only callback type. A `RepeatingCallback` with a // `Passed()` argument is really a `OnceCallback` and should eventually be // migrated. static_assert( BindArgument::template ForwardedAs:: template ToParamWithType::kMoveOnlyTypeMustUseBasePassed, "base::BindRepeating() argument is a move-only type. Use base::Passed() " "instead of std::move() to transfer ownership from the callback to the " "bound functor."); static_assert( BindArgument::template ForwardedAs:: template ToParamWithType::kCanBeForwardedToBoundFunctor, "Type mismatch between bound argument and bound functor's parameter."); static_assert(BindArgument::template BoundAs::template StoredAs< Storage>::kMoveOnlyTypeMustUseStdMove, "Attempting to bind a move-only type. Use std::move() to " "transfer ownership to the created callback."); // In practice, this static_assert should be quite rare as the storage type // is deduced from the arguments passed to `BindOnce()`/`BindRepeating()`. static_assert( BindArgument::template BoundAs::template StoredAs< Storage>::kBindArgumentCanBeCaptured, "Cannot capture argument: is the argument copyable or movable?"); }; // 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; }; template struct AssertBindArgIsNotBasePassed : public std::true_type {}; template struct AssertBindArgIsNotBasePassed> : public std::false_type {}; // 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