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