1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_BIND_H_ 6 #define BASE_BIND_H_ 7 8 #include "base/bind_internal.h" 9 10 // ----------------------------------------------------------------------------- 11 // Usage documentation 12 // ----------------------------------------------------------------------------- 13 // 14 // See //docs/callback.md for documentation. 15 // 16 // 17 // ----------------------------------------------------------------------------- 18 // Implementation notes 19 // ----------------------------------------------------------------------------- 20 // 21 // If you're reading the implementation, before proceeding further, you should 22 // read the top comment of base/bind_internal.h for a definition of common 23 // terms and concepts. 24 25 namespace base { 26 27 namespace internal { 28 29 // IsOnceCallback<T> is a std::true_type if |T| is a OnceCallback. 30 template <typename T> 31 struct IsOnceCallback : std::false_type {}; 32 33 template <typename Signature> 34 struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {}; 35 36 // Helper to assert that parameter |i| of type |Arg| can be bound, which means: 37 // - |Arg| can be retained internally as |Storage|. 38 // - |Arg| can be forwarded as |Unwrapped| to |Param|. 39 template <size_t i, 40 typename Arg, 41 typename Storage, 42 typename Unwrapped, 43 typename Param> 44 struct AssertConstructible { 45 private: 46 static constexpr bool param_is_forwardable = 47 std::is_constructible<Param, Unwrapped>::value; 48 // Unlike the check for binding into storage below, the check for 49 // forwardability drops the const qualifier for repeating callbacks. This is 50 // to try to catch instances where std::move()--which forwards as a const 51 // reference with repeating callbacks--is used instead of base::Passed(). 52 static_assert( 53 param_is_forwardable || 54 !std::is_constructible<Param, typename std::decay<Unwrapped>::type&&>::value, 55 "Bound argument |i| is move-only but will be forwarded by copy. " 56 "Ensure |Arg| is bound using base::Passed(), not std::move()."); 57 static_assert( 58 param_is_forwardable, 59 "Bound argument |i| of type |Arg| cannot be forwarded as " 60 "|Unwrapped| to the bound functor, which declares it as |Param|."); 61 62 static constexpr bool arg_is_storable = 63 std::is_constructible<Storage, Arg>::value; 64 static_assert(arg_is_storable || 65 !std::is_constructible<Storage, typename std::decay<Arg>::type&&>::value, 66 "Bound argument |i| is move-only but will be bound by copy. " 67 "Ensure |Arg| is mutable and bound using std::move()."); 68 static_assert(arg_is_storable, 69 "Bound argument |i| of type |Arg| cannot be converted and " 70 "bound as |Storage|."); 71 }; 72 73 // Takes three same-length TypeLists, and applies AssertConstructible for each 74 // triples. 75 template <typename Index, 76 typename Args, 77 typename UnwrappedTypeList, 78 typename ParamsList> 79 struct AssertBindArgsValidity; 80 81 template <size_t... Ns, 82 typename... Args, 83 typename... Unwrapped, 84 typename... Params> 85 struct AssertBindArgsValidity<IndexSequence<Ns...>, 86 TypeList<Args...>, 87 TypeList<Unwrapped...>, 88 TypeList<Params...>> 89 : AssertConstructible<Ns, Args, typename std::decay<Args>::type, Unwrapped, Params>... { 90 static constexpr bool ok = true; 91 }; 92 93 // The implementation of TransformToUnwrappedType below. 94 template <bool is_once, typename T> 95 struct TransformToUnwrappedTypeImpl; 96 97 template <typename T> 98 struct TransformToUnwrappedTypeImpl<true, T> { 99 using StoredType = typename std::decay<T>::type; 100 using ForwardType = StoredType&&; 101 using Unwrapped = decltype(Unwrap(std::declval<ForwardType>())); 102 }; 103 104 template <typename T> 105 struct TransformToUnwrappedTypeImpl<false, T> { 106 using StoredType = typename std::decay<T>::type; 107 using ForwardType = const StoredType&; 108 using Unwrapped = decltype(Unwrap(std::declval<ForwardType>())); 109 }; 110 111 // Transform |T| into `Unwrapped` type, which is passed to the target function. 112 // Example: 113 // In is_once == true case, 114 // `int&&` -> `int&&`, 115 // `const int&` -> `int&&`, 116 // `OwnedWrapper<int>&` -> `int*&&`. 117 // In is_once == false case, 118 // `int&&` -> `const int&`, 119 // `const int&` -> `const int&`, 120 // `OwnedWrapper<int>&` -> `int* const &`. 121 template <bool is_once, typename T> 122 using TransformToUnwrappedType = 123 typename TransformToUnwrappedTypeImpl<is_once, T>::Unwrapped; 124 125 // Transforms |Args| into `Unwrapped` types, and packs them into a TypeList. 126 // If |is_method| is true, tries to dereference the first argument to support 127 // smart pointers. 128 template <bool is_once, bool is_method, typename... Args> 129 struct MakeUnwrappedTypeListImpl { 130 using Type = TypeList<TransformToUnwrappedType<is_once, Args>...>; 131 }; 132 133 // Performs special handling for this pointers. 134 // Example: 135 // int* -> int*, 136 // std::unique_ptr<int> -> int*. 137 template <bool is_once, typename Receiver, typename... Args> 138 struct MakeUnwrappedTypeListImpl<is_once, true, Receiver, Args...> { 139 using UnwrappedReceiver = TransformToUnwrappedType<is_once, Receiver>; 140 using Type = TypeList<decltype(&*std::declval<UnwrappedReceiver>()), 141 TransformToUnwrappedType<is_once, Args>...>; 142 }; 143 144 template <bool is_once, bool is_method, typename... Args> 145 using MakeUnwrappedTypeList = 146 typename MakeUnwrappedTypeListImpl<is_once, is_method, Args...>::Type; 147 148 } // namespace internal 149 150 // Bind as OnceCallback. 151 template <typename Functor, typename... Args> 152 inline OnceCallback<MakeUnboundRunType<Functor, Args...>> 153 BindOnce(Functor&& functor, Args&&... args) { 154 static_assert( 155 !internal::IsOnceCallback<typename std::decay<Functor>::type>() || 156 (std::is_rvalue_reference<Functor&&>() && 157 !std::is_const<typename std::remove_reference<Functor>::type>()), 158 "BindOnce requires non-const rvalue for OnceCallback binding." 159 " I.e.: base::BindOnce(std::move(callback))."); 160 161 // This block checks if each |args| matches to the corresponding params of the 162 // target function. This check does not affect the behavior of Bind, but its 163 // error message should be more readable. 164 using Helper = internal::BindTypeHelper<Functor, Args...>; 165 using FunctorTraits = typename Helper::FunctorTraits; 166 using BoundArgsList = typename Helper::BoundArgsList; 167 using UnwrappedArgsList = 168 internal::MakeUnwrappedTypeList<true, FunctorTraits::is_method, 169 Args&&...>; 170 using BoundParamsList = typename Helper::BoundParamsList; 171 static_assert(internal::AssertBindArgsValidity< 172 MakeIndexSequence<Helper::num_bounds>, BoundArgsList, 173 UnwrappedArgsList, BoundParamsList>::ok, 174 "The bound args need to be convertible to the target params."); 175 176 using BindState = internal::MakeBindStateType<Functor, Args...>; 177 using UnboundRunType = MakeUnboundRunType<Functor, Args...>; 178 using Invoker = internal::Invoker<BindState, UnboundRunType>; 179 using CallbackType = OnceCallback<UnboundRunType>; 180 181 // Store the invoke func into PolymorphicInvoke before casting it to 182 // InvokeFuncStorage, so that we can ensure its type matches to 183 // PolymorphicInvoke, to which CallbackType will cast back. 184 using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke; 185 PolymorphicInvoke invoke_func = &Invoker::RunOnce; 186 187 using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage; 188 return CallbackType(new BindState( 189 reinterpret_cast<InvokeFuncStorage>(invoke_func), 190 std::forward<Functor>(functor), 191 std::forward<Args>(args)...)); 192 } 193 194 // Bind as RepeatingCallback. 195 template <typename Functor, typename... Args> 196 inline RepeatingCallback<MakeUnboundRunType<Functor, Args...>> 197 BindRepeating(Functor&& functor, Args&&... args) { 198 static_assert( 199 !internal::IsOnceCallback<typename std::decay<Functor>::type>(), 200 "BindRepeating cannot bind OnceCallback. Use BindOnce with std::move()."); 201 202 // This block checks if each |args| matches to the corresponding params of the 203 // target function. This check does not affect the behavior of Bind, but its 204 // error message should be more readable. 205 using Helper = internal::BindTypeHelper<Functor, Args...>; 206 using FunctorTraits = typename Helper::FunctorTraits; 207 using BoundArgsList = typename Helper::BoundArgsList; 208 using UnwrappedArgsList = 209 internal::MakeUnwrappedTypeList<false, FunctorTraits::is_method, 210 Args&&...>; 211 using BoundParamsList = typename Helper::BoundParamsList; 212 static_assert(internal::AssertBindArgsValidity< 213 MakeIndexSequence<Helper::num_bounds>, BoundArgsList, 214 UnwrappedArgsList, BoundParamsList>::ok, 215 "The bound args need to be convertible to the target params."); 216 217 using BindState = internal::MakeBindStateType<Functor, Args...>; 218 using UnboundRunType = MakeUnboundRunType<Functor, Args...>; 219 using Invoker = internal::Invoker<BindState, UnboundRunType>; 220 using CallbackType = RepeatingCallback<UnboundRunType>; 221 222 // Store the invoke func into PolymorphicInvoke before casting it to 223 // InvokeFuncStorage, so that we can ensure its type matches to 224 // PolymorphicInvoke, to which CallbackType will cast back. 225 using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke; 226 PolymorphicInvoke invoke_func = &Invoker::Run; 227 228 using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage; 229 return CallbackType(new BindState( 230 reinterpret_cast<InvokeFuncStorage>(invoke_func), 231 std::forward<Functor>(functor), 232 std::forward<Args>(args)...)); 233 } 234 235 // Unannotated Bind. 236 // TODO(tzik): Deprecate this and migrate to OnceCallback and 237 // RepeatingCallback, once they get ready. 238 template <typename Functor, typename... Args> 239 inline Callback<MakeUnboundRunType<Functor, Args...>> 240 Bind(Functor&& functor, Args&&... args) { 241 return BindRepeating(std::forward<Functor>(functor), 242 std::forward<Args>(args)...); 243 } 244 245 // Special cases for binding to a base::Callback without extra bound arguments. 246 template <typename Signature> 247 OnceCallback<Signature> BindOnce(OnceCallback<Signature> closure) { 248 return closure; 249 } 250 251 template <typename Signature> 252 RepeatingCallback<Signature> BindRepeating( 253 RepeatingCallback<Signature> closure) { 254 return closure; 255 } 256 257 template <typename Signature> 258 Callback<Signature> Bind(Callback<Signature> closure) { 259 return closure; 260 } 261 262 } // namespace base 263 264 #endif // BASE_BIND_H_ 265