blob: 88e764547f81677ac6c3f72b8a026642c67681d2 [file] [log] [blame]
[email protected]b38d3572011-02-15 01:27:381// 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_INTERNAL_H_
6#define BASE_BIND_INTERNAL_H_
[email protected]b38d3572011-02-15 01:27:387
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
9
tzik1068f1be2016-06-03 07:25:2010#include <tuple>
vmpstrc52317f2015-11-18 08:43:2611#include <type_traits>
12
[email protected]b38d3572011-02-15 01:27:3813#include "base/bind_helpers.h"
[email protected]59eff912011-02-18 23:29:3114#include "base/callback_internal.h"
[email protected]8217d4542011-10-01 06:31:4115#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
[email protected]93540582011-05-16 22:35:1416#include "base/memory/weak_ptr.h"
[email protected]b38d3572011-02-15 01:27:3817#include "base/template_util.h"
tzik8ce65702015-02-05 19:11:2618#include "base/tuple.h"
[email protected]054ac7542011-02-27 01:25:5919#include "build/build_config.h"
20
[email protected]b38d3572011-02-15 01:27:3821namespace base {
22namespace internal {
23
[email protected]24292642012-07-12 20:06:4024// See base/callback.h for user documentation.
25//
26//
[email protected]7296f2762011-11-21 19:23:4427// CONCEPTS:
tzik99de02b2016-07-01 05:54:1228// Functor -- A movable type representing something that should be called.
29// All function pointers and Callback<> are functors even if the
30// invocation syntax differs.
[email protected]7296f2762011-11-21 19:23:4431// RunType -- A function type (as opposed to function _pointer_ type) for
tzik99de02b2016-07-01 05:54:1232// a Callback<>::Run(). Usually just a convenience typedef.
tzikce3ecf82015-12-15 06:41:4933// (Bound)Args -- A set of types that stores the arguments.
[email protected]b38d3572011-02-15 01:27:3834//
[email protected]7296f2762011-11-21 19:23:4435// Types:
[email protected]7296f2762011-11-21 19:23:4436// ForceVoidReturn<> -- Helper class for translating function signatures to
37// equivalent forms with a "void" return type.
tzik99de02b2016-07-01 05:54:1238// FunctorTraits<> -- Type traits used to determine the correct RunType and
39// invocation manner for a Functor. This is where function
[email protected]7296f2762011-11-21 19:23:4440// signature adapters are applied.
tzik99de02b2016-07-01 05:54:1241// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik8ce65702015-02-05 19:11:2642// Handle the differing syntaxes needed for WeakPtr<>
tzik99de02b2016-07-01 05:54:1243// support. This is separate from Invoker to avoid creating
44// multiple version of Invoker<>.
45// Invoker<> -- Unwraps the curried parameters and executes the Functor.
[email protected]7296f2762011-11-21 19:23:4446// BindState<> -- Stores the curried parameters, and is the main entry point
tzik99de02b2016-07-01 05:54:1247// into the Bind() system.
[email protected]4346ef912011-02-19 00:52:1548
tzikc1db72652016-07-08 09:42:3849template <typename...>
50struct make_void {
51 using type = void;
52};
53
54// A clone of C++17 std::void_t.
55// Unlike the original version, we need |make_void| as a helper struct to avoid
56// a C++14 defect.
57// ref: http://en.cppreference.com/w/cpp/types/void_t
58// ref: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
59template <typename... Ts>
60using void_t = typename make_void<Ts...>::type;
61
62template <typename Callable,
63 typename Signature = decltype(&Callable::operator())>
64struct ExtractCallableRunTypeImpl;
65
66template <typename Callable, typename R, typename... Args>
67struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> {
68 using Type = R(Args...);
69};
70
71// Evaluated to RunType of the given callable type.
72// Example:
73// auto f = [](int, char*) { return 0.1; };
74// ExtractCallableRunType<decltype(f)>
75// is evaluated to
76// double(int, char*);
77template <typename Callable>
78using ExtractCallableRunType =
79 typename ExtractCallableRunTypeImpl<Callable>::Type;
80
81// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator()
82// and convertible to the corresponding function pointer. Otherwise, it's
83// std::false_type.
84// Example:
85// IsConvertibleToRunType<void(*)()>::value is false.
86//
87// struct Foo {};
88// IsConvertibleToRunType<void(Foo::*)()>::value is false.
89//
90// auto f = []() {};
91// IsConvertibleToRunType<decltype(f)>::value is true.
92//
93// int i = 0;
94// auto g = [i]() {};
95// IsConvertibleToRunType<decltype(g)>::value is false.
96template <typename Functor, typename SFINAE = void>
97struct IsConvertibleToRunType : std::false_type {};
98
99template <typename Callable>
100struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
101 : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
102
tzik401dd3672014-11-26 07:54:58103// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
104// pointer to a RefCounted type.
105// Implementation note: This non-specialized case handles zero-arity case only.
106// Non-zero-arity cases should be handled by the specialization below.
107template <typename... Args>
tzik403cb6c2016-03-10 07:17:25108struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik401dd3672014-11-26 07:54:58109
110// Implementation note: Select true_type if the first parameter is a raw pointer
111// to a RefCounted type. Otherwise, skip the first parameter and check rest of
112// parameters recursively.
113template <typename T, typename... Args>
114struct HasRefCountedTypeAsRawPtr<T, Args...>
vmpstrc52317f2015-11-18 08:43:26115 : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value,
tzik403cb6c2016-03-10 07:17:25116 std::true_type,
vmpstrc52317f2015-11-18 08:43:26117 HasRefCountedTypeAsRawPtr<Args...>>::type {};
tzik401dd3672014-11-26 07:54:58118
[email protected]7296f2762011-11-21 19:23:44119// ForceVoidReturn<>
120//
121// Set of templates that support forcing the function return type to void.
122template <typename Sig>
123struct ForceVoidReturn;
124
tzikc82149922014-11-20 10:09:45125template <typename R, typename... Args>
126struct ForceVoidReturn<R(Args...)> {
tzik99de02b2016-07-01 05:54:12127 using RunType = void(Args...);
[email protected]fccef1552011-11-28 22:13:54128};
129
[email protected]7296f2762011-11-21 19:23:44130// FunctorTraits<>
131//
132// See description at top of file.
tzikc1db72652016-07-08 09:42:38133template <typename Functor, typename SFINAE = void>
tzik99de02b2016-07-01 05:54:12134struct FunctorTraits;
135
tzikc1db72652016-07-08 09:42:38136// For a callable type that is convertible to the corresponding function type.
137// This specialization is intended to allow binding captureless lambdas by
138// base::Bind(), based on the fact that captureless lambdas can be convertible
139// to the function type while capturing lambdas can't.
140template <typename Functor>
141struct FunctorTraits<
142 Functor,
143 typename std::enable_if<IsConvertibleToRunType<Functor>::value>::type> {
144 using RunType = ExtractCallableRunType<Functor>;
145 static constexpr bool is_method = false;
146 static constexpr bool is_nullable = false;
147
148 template <typename... RunArgs>
149 static ExtractReturnType<RunType>
150 Invoke(const Functor& functor, RunArgs&&... args) {
151 return functor(std::forward<RunArgs>(args)...);
152 }
153};
154
tzik99de02b2016-07-01 05:54:12155// For functions.
156template <typename R, typename... Args>
157struct FunctorTraits<R (*)(Args...)> {
158 using RunType = R(Args...);
159 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38160 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12161
162 template <typename... RunArgs>
163 static R Invoke(R (*function)(Args...), RunArgs&&... args) {
164 return function(std::forward<RunArgs>(args)...);
165 }
[email protected]7296f2762011-11-21 19:23:44166};
167
tzik99de02b2016-07-01 05:54:12168#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
169
170// For functions.
171template <typename R, typename... Args>
172struct FunctorTraits<R(__stdcall*)(Args...)> {
173 using RunType = R(Args...);
174 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38175 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12176
177 template <typename... RunArgs>
178 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
179 return function(std::forward<RunArgs>(args)...);
180 }
181};
182
183// For functions.
184template <typename R, typename... Args>
185struct FunctorTraits<R(__fastcall*)(Args...)> {
186 using RunType = R(Args...);
187 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38188 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12189
190 template <typename... RunArgs>
191 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
192 return function(std::forward<RunArgs>(args)...);
193 }
194};
195
196#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
197
198// For methods.
199template <typename R, typename Receiver, typename... Args>
200struct FunctorTraits<R (Receiver::*)(Args...)> {
201 using RunType = R(Receiver*, Args...);
202 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38203 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12204
205 template <typename ReceiverPtr, typename... RunArgs>
206 static R Invoke(R (Receiver::*method)(Args...),
207 ReceiverPtr&& receiver_ptr,
208 RunArgs&&... args) {
209 // Clang skips CV qualifier check on a method pointer invocation when the
210 // receiver is a subclass. Store the receiver into a const reference to
211 // T to ensure the CV check works.
212 // https://llvm.org/bugs/show_bug.cgi?id=27037
213 Receiver& receiver = *receiver_ptr;
214 return (receiver.*method)(std::forward<RunArgs>(args)...);
215 }
216};
217
218// For const methods.
219template <typename R, typename Receiver, typename... Args>
220struct FunctorTraits<R (Receiver::*)(Args...) const> {
221 using RunType = R(const Receiver*, Args...);
222 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38223 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12224
225 template <typename ReceiverPtr, typename... RunArgs>
226 static R Invoke(R (Receiver::*method)(Args...) const,
227 ReceiverPtr&& receiver_ptr,
228 RunArgs&&... args) {
229 // Clang skips CV qualifier check on a method pointer invocation when the
230 // receiver is a subclass. Store the receiver into a const reference to
231 // T to ensure the CV check works.
232 // https://llvm.org/bugs/show_bug.cgi?id=27037
233 const Receiver& receiver = *receiver_ptr;
234 return (receiver.*method)(std::forward<RunArgs>(args)...);
235 }
236};
237
238// For IgnoreResults.
[email protected]7296f2762011-11-21 19:23:44239template <typename T>
tzik99de02b2016-07-01 05:54:12240struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik3bc7779b2015-12-19 09:18:46241 using RunType =
tzik99de02b2016-07-01 05:54:12242 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
243
244 template <typename IgnoreResultType, typename... RunArgs>
245 static void Invoke(IgnoreResultType&& ignore_result_helper,
246 RunArgs&&... args) {
tzikff54a5b152016-08-31 11:50:41247 FunctorTraits<T>::Invoke(
248 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
249 std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12250 }
[email protected]7296f2762011-11-21 19:23:44251};
252
tzik99de02b2016-07-01 05:54:12253// For Callbacks.
tzik27d1e312016-09-13 05:28:59254template <typename R, typename... Args,
255 CopyMode copy_mode, RepeatMode repeat_mode>
256struct FunctorTraits<Callback<R(Args...), copy_mode, repeat_mode>> {
tzik99de02b2016-07-01 05:54:12257 using RunType = R(Args...);
258 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38259 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12260
261 template <typename CallbackType, typename... RunArgs>
262 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
263 DCHECK(!callback.is_null());
264 return std::forward<CallbackType>(callback).Run(
265 std::forward<RunArgs>(args)...);
266 }
[email protected]7296f2762011-11-21 19:23:44267};
268
[email protected]7296f2762011-11-21 19:23:44269// InvokeHelper<>
270//
tzik99de02b2016-07-01 05:54:12271// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
[email protected]7296f2762011-11-21 19:23:44272//
273// The normal type just calls the underlying runnable.
274//
tzik99de02b2016-07-01 05:54:12275// WeakCalls need special syntax that is applied to the first argument to check
276// if they should no-op themselves.
tzikee248722016-06-01 08:22:51277template <bool is_weak_call, typename ReturnType>
[email protected]7296f2762011-11-21 19:23:44278struct InvokeHelper;
279
tzikee248722016-06-01 08:22:51280template <typename ReturnType>
281struct InvokeHelper<false, ReturnType> {
tzik99de02b2016-07-01 05:54:12282 template <typename Functor, typename... RunArgs>
283 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
284 using Traits = FunctorTraits<typename std::decay<Functor>::type>;
285 return Traits::Invoke(std::forward<Functor>(functor),
286 std::forward<RunArgs>(args)...);
[email protected]7296f2762011-11-21 19:23:44287 }
288};
289
tzikee248722016-06-01 08:22:51290template <typename ReturnType>
291struct InvokeHelper<true, ReturnType> {
[email protected]7296f2762011-11-21 19:23:44292 // WeakCalls are only supported for functions with a void return type.
293 // Otherwise, the function result would be undefined if the the WeakPtr<>
294 // is invalidated.
tzik403cb6c2016-03-10 07:17:25295 static_assert(std::is_void<ReturnType>::value,
avi4ec0dff2015-11-24 14:26:24296 "weak_ptrs can only bind to methods without return values");
[email protected]c18b1052011-03-24 02:02:17297
tzik99de02b2016-07-01 05:54:12298 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
299 static inline void MakeItSo(Functor&& functor,
tzik33871d82016-07-14 12:12:06300 BoundWeakPtr&& weak_ptr,
tzik99de02b2016-07-01 05:54:12301 RunArgs&&... args) {
302 if (!weak_ptr)
303 return;
304 using Traits = FunctorTraits<typename std::decay<Functor>::type>;
305 Traits::Invoke(std::forward<Functor>(functor),
306 std::forward<BoundWeakPtr>(weak_ptr),
307 std::forward<RunArgs>(args)...);
308 }
309};
[email protected]b38d3572011-02-15 01:27:38310
[email protected]7296f2762011-11-21 19:23:44311// Invoker<>
312//
313// See description at the top of the file.
tzikcaf1d84b2016-06-28 12:22:21314template <typename StorageType, typename UnboundRunType>
[email protected]7296f2762011-11-21 19:23:44315struct Invoker;
316
tzikcaf1d84b2016-06-28 12:22:21317template <typename StorageType, typename R, typename... UnboundArgs>
318struct Invoker<StorageType, R(UnboundArgs...)> {
tzik27d1e312016-09-13 05:28:59319 static R RunOnce(BindStateBase* base, UnboundArgs&&... unbound_args) {
320 // Local references to make debugger stepping easier. If in a debugger,
321 // you really want to warp ahead and step through the
322 // InvokeHelper<>::MakeItSo() call below.
323 StorageType* storage = static_cast<StorageType*>(base);
324 static constexpr size_t num_bound_args =
325 std::tuple_size<decltype(storage->bound_args_)>::value;
326 return RunImpl(std::move(storage->functor_),
327 std::move(storage->bound_args_),
328 MakeIndexSequence<num_bound_args>(),
329 std::forward<UnboundArgs>(unbound_args)...);
330 }
331
tzika43eff02016-03-09 05:46:05332 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
[email protected]7296f2762011-11-21 19:23:44333 // Local references to make debugger stepping easier. If in a debugger,
334 // you really want to warp ahead and step through the
335 // InvokeHelper<>::MakeItSo() call below.
tzikcaf1d84b2016-06-28 12:22:21336 const StorageType* storage = static_cast<StorageType*>(base);
337 static constexpr size_t num_bound_args =
338 std::tuple_size<decltype(storage->bound_args_)>::value;
tzik99de02b2016-07-01 05:54:12339 return RunImpl(storage->functor_,
tzikcaf1d84b2016-06-28 12:22:21340 storage->bound_args_,
341 MakeIndexSequence<num_bound_args>(),
342 std::forward<UnboundArgs>(unbound_args)...);
343 }
344
tzik99de02b2016-07-01 05:54:12345 private:
346 template <typename Functor, typename BoundArgsTuple, size_t... indices>
347 static inline R RunImpl(Functor&& functor,
tzikcaf1d84b2016-06-28 12:22:21348 BoundArgsTuple&& bound,
349 IndexSequence<indices...>,
350 UnboundArgs&&... unbound_args) {
351 static constexpr bool is_method =
tzik99de02b2016-07-01 05:54:12352 FunctorTraits<typename std::decay<Functor>::type>::is_method;
tzikcaf1d84b2016-06-28 12:22:21353
354 using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
355 static constexpr bool is_weak_call =
356 IsWeakMethod<is_method,
357 typename std::tuple_element<
358 indices,
359 DecayedArgsTuple>::type...>::value;
360
tzikee248722016-06-01 08:22:51361 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik99de02b2016-07-01 05:54:12362 std::forward<Functor>(functor),
363 Unwrap(base::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzika43eff02016-03-09 05:46:05364 std::forward<UnboundArgs>(unbound_args)...);
[email protected]fccef1552011-11-28 22:13:54365 }
366};
367
tzikcaf1d84b2016-06-28 12:22:21368// Used to implement MakeUnboundRunType.
369template <typename Functor, typename... BoundArgs>
370struct MakeUnboundRunTypeImpl {
tzik99de02b2016-07-01 05:54:12371 using RunType =
372 typename FunctorTraits<typename std::decay<Functor>::type>::RunType;
tzikcaf1d84b2016-06-28 12:22:21373 using ReturnType = ExtractReturnType<RunType>;
374 using Args = ExtractArgs<RunType>;
375 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
376 using Type = MakeFunctionType<ReturnType, UnboundArgs>;
377};
tzikc1db72652016-07-08 09:42:38378template <typename Functor>
379typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type
380IsNull(const Functor& functor) {
381 return !functor;
382}
383
384template <typename Functor>
385typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type
386IsNull(const Functor&) {
387 return false;
388}
tzikcaf1d84b2016-06-28 12:22:21389
tzik59aa6bb12016-09-08 10:58:53390template <typename Functor, typename... BoundArgs>
391struct BindState;
392
393template <typename BindStateType, typename SFINAE = void>
394struct CancellationChecker {
tzik1fdcca32016-09-14 07:15:00395 static constexpr bool is_cancellable = false;
tzik59aa6bb12016-09-08 10:58:53396 static bool Run(const BindStateBase*) {
397 return false;
398 }
399};
400
401template <typename Functor, typename... BoundArgs>
402struct CancellationChecker<
403 BindState<Functor, BoundArgs...>,
404 typename std::enable_if<IsWeakMethod<FunctorTraits<Functor>::is_method,
405 BoundArgs...>::value>::type> {
tzik1fdcca32016-09-14 07:15:00406 static constexpr bool is_cancellable = true;
tzik59aa6bb12016-09-08 10:58:53407 static bool Run(const BindStateBase* base) {
408 using BindStateType = BindState<Functor, BoundArgs...>;
409 const BindStateType* bind_state = static_cast<const BindStateType*>(base);
410 return !base::get<0>(bind_state->bound_args_);
411 }
412};
413
tzik44adf072016-10-07 04:34:54414template <typename Signature,
415 typename... BoundArgs,
416 CopyMode copy_mode,
417 RepeatMode repeat_mode>
418struct CancellationChecker<
419 BindState<Callback<Signature, copy_mode, repeat_mode>, BoundArgs...>> {
tzik1fdcca32016-09-14 07:15:00420 static constexpr bool is_cancellable = true;
tzik59aa6bb12016-09-08 10:58:53421 static bool Run(const BindStateBase* base) {
tzik44adf072016-10-07 04:34:54422 using Functor = Callback<Signature, copy_mode, repeat_mode>;
tzik59aa6bb12016-09-08 10:58:53423 using BindStateType = BindState<Functor, BoundArgs...>;
424 const BindStateType* bind_state = static_cast<const BindStateType*>(base);
425 return bind_state->functor_.IsCancelled();
426 }
427};
428
dcheng172b6ad2016-09-24 05:05:57429// Template helpers to detect using Bind() on a base::Callback without any
430// additional arguments. In that case, the original base::Callback object should
431// just be directly used.
432template <typename Functor, typename... BoundArgs>
433struct BindingCallbackWithNoArgs {
434 static constexpr bool value = false;
435};
436
437template <typename Signature,
438 typename... BoundArgs,
439 CopyMode copy_mode,
440 RepeatMode repeat_mode>
441struct BindingCallbackWithNoArgs<Callback<Signature, copy_mode, repeat_mode>,
442 BoundArgs...> {
443 static constexpr bool value = sizeof...(BoundArgs) == 0;
444};
445
[email protected]7296f2762011-11-21 19:23:44446// BindState<>
447//
tzik99de02b2016-07-01 05:54:12448// This stores all the state passed into Bind().
449template <typename Functor, typename... BoundArgs>
450struct BindState final : BindStateBase {
tzik1fdcca32016-09-14 07:15:00451 using IsCancellable = std::integral_constant<
452 bool, CancellationChecker<BindState>::is_cancellable>;
453
tzikbfe66122016-07-08 14:14:01454 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzik1886c272016-09-08 05:45:38455 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
456 ForwardFunctor&& functor,
457 ForwardBoundArgs&&... bound_args)
tzik1fdcca32016-09-14 07:15:00458 // IsCancellable is std::false_type if the CancellationChecker<>::Run
459 // returns always false. Otherwise, it's std::true_type.
460 : BindState(IsCancellable{},
461 invoke_func,
462 std::forward<ForwardFunctor>(functor),
dcheng172b6ad2016-09-24 05:05:57463 std::forward<ForwardBoundArgs>(bound_args)...) {
464 static_assert(!BindingCallbackWithNoArgs<Functor, BoundArgs...>::value,
465 "Attempting to bind a base::Callback with no additional "
466 "arguments: save a heap allocation and use the original "
467 "base::Callback object");
468 }
tzik1fdcca32016-09-14 07:15:00469
470 Functor functor_;
471 std::tuple<BoundArgs...> bound_args_;
472
473 private:
474 template <typename ForwardFunctor, typename... ForwardBoundArgs>
475 explicit BindState(std::true_type,
476 BindStateBase::InvokeFuncStorage invoke_func,
477 ForwardFunctor&& functor,
478 ForwardBoundArgs&&... bound_args)
tzik59aa6bb12016-09-08 10:58:53479 : BindStateBase(invoke_func, &Destroy,
480 &CancellationChecker<BindState>::Run),
tzikff54a5b152016-08-31 11:50:41481 functor_(std::forward<ForwardFunctor>(functor)),
tzik99de02b2016-07-01 05:54:12482 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzikc1db72652016-07-08 09:42:38483 DCHECK(!IsNull(functor_));
tzik99de02b2016-07-01 05:54:12484 }
[email protected]7296f2762011-11-21 19:23:44485
tzik1fdcca32016-09-14 07:15:00486 template <typename ForwardFunctor, typename... ForwardBoundArgs>
487 explicit BindState(std::false_type,
488 BindStateBase::InvokeFuncStorage invoke_func,
489 ForwardFunctor&& functor,
490 ForwardBoundArgs&&... bound_args)
491 : BindStateBase(invoke_func, &Destroy),
492 functor_(std::forward<ForwardFunctor>(functor)),
493 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
494 DCHECK(!IsNull(functor_));
495 }
dmichael7d09007e2014-12-18 22:30:11496
taptede7e804c2015-05-14 08:03:32497 ~BindState() {}
498
tzik30e0c312016-09-21 08:06:54499 static void Destroy(const BindStateBase* self) {
500 delete static_cast<const BindState*>(self);
taptede7e804c2015-05-14 08:03:32501 }
[email protected]fccef1552011-11-28 22:13:54502};
503
tzik99de02b2016-07-01 05:54:12504// Used to implement MakeBindStateType.
505template <bool is_method, typename Functor, typename... BoundArgs>
506struct MakeBindStateTypeImpl;
507
508template <typename Functor, typename... BoundArgs>
509struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
510 static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
511 "A parameter is a refcounted type and needs scoped_refptr.");
512 using Type = BindState<typename std::decay<Functor>::type,
513 typename std::decay<BoundArgs>::type...>;
514};
515
516template <typename Functor>
517struct MakeBindStateTypeImpl<true, Functor> {
518 using Type = BindState<typename std::decay<Functor>::type>;
519};
520
521template <typename Functor, typename Receiver, typename... BoundArgs>
522struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
523 static_assert(
524 !std::is_array<typename std::remove_reference<Receiver>::type>::value,
525 "First bound argument to a method cannot be an array.");
526 static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
527 "A parameter is a refcounted type and needs scoped_refptr.");
528
529 private:
530 using DecayedReceiver = typename std::decay<Receiver>::type;
531
532 public:
533 using Type = BindState<
534 typename std::decay<Functor>::type,
535 typename std::conditional<
536 std::is_pointer<DecayedReceiver>::value,
537 scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>,
538 DecayedReceiver>::type,
539 typename std::decay<BoundArgs>::type...>;
540};
541
542template <typename Functor, typename... BoundArgs>
543using MakeBindStateType = typename MakeBindStateTypeImpl<
544 FunctorTraits<typename std::decay<Functor>::type>::is_method,
545 Functor,
546 BoundArgs...>::Type;
547
[email protected]b38d3572011-02-15 01:27:38548} // namespace internal
tzikcaf1d84b2016-06-28 12:22:21549
550// Returns a RunType of bound functor.
551// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
552template <typename Functor, typename... BoundArgs>
553using MakeUnboundRunType =
554 typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type;
555
[email protected]b38d3572011-02-15 01:27:38556} // namespace base
557
558#endif // BASE_BIND_INTERNAL_H_