Chromium Code Reviews| Index: base/bind_internal.h |
| diff --git a/base/bind_internal.h b/base/bind_internal.h |
| index 6b692a85a9d5424231489d964226d38f5b5932da..eb69824ddade47674bc0c1d08e188cd1f8c2628c 100644 |
| --- a/base/bind_internal.h |
| +++ b/base/bind_internal.h |
| @@ -46,6 +46,56 @@ namespace internal { |
| // BindState<> -- Stores the curried parameters, and is the main entry point |
| // into the Bind() system. |
| +template <typename...> |
| +struct make_void { |
| + using type = void; |
| +}; |
| + |
| +// A clone of C++17 std::void_t. |
| +// Unlike to the original version, we need |make_void| as a helper struct to |
|
Yuta Kitamura
2016/07/01 09:02:33
nit: Remove "to" after "Unlike"
tzik
2016/07/01 09:58:08
Done.
|
| +// avoid a C++14 defect. |
| +// ref: http://en.cppreference.com/w/cpp/types/void_t |
| +// ref: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558 |
| +template <typename... Ts> |
| +using void_t = typename make_void<Ts...>::type; |
| + |
| +template <typename Lambda, typename Signature = decltype(&Lambda::operator())> |
| +struct ExtractLambdaRunTypeImpl; |
| + |
| +template <typename Lambda, typename R, typename... Args> |
| +struct ExtractLambdaRunTypeImpl<Lambda, R(Lambda::*)(Args...) const> { |
| + using Type = R(Args...); |
| +}; |
| + |
| +// Evaluated to RunType of the given C++11 lambda expressien type. |
|
Yuta Kitamura
2016/07/01 09:02:33
nit: expressien
tzik
2016/07/01 09:58:08
Done.
|
| +// Example: |
| +// ExtractLambdaRunType<[](int, char*) { return 0.1; }> |
| +// is evaluated to |
| +// double(int, char*); |
| +template <typename Lambda> |
| +using ExtractLambdaRunType = typename ExtractLambdaRunTypeImpl<Lambda>::Type; |
| + |
| +// IsCapturelessLambda<Functor> is a std::true_type if |Functor| is a |
| +// captureless lambda expression type. |
| +// Example: |
| +// IsCapturelessLambda<void(*)()>::value is false. |
| +// |
| +// struct Foo {}; |
| +// IsCapturelessLambda<void(Foo::*)()>::value is false. |
| +// |
| +// auto f = []() {}; |
| +// IsCapturelessLambda<decltype(f)>::value is true. |
| +// |
| +// int i = 0; |
| +// auto g = [i]() {}; |
| +// IsCapturelessLambda<decltype(g)>::value is false. |
| +template <typename Functor, typename SFINAE = void> |
| +struct IsCapturelessLambda : std::false_type {}; |
| + |
| +template <typename Lambda> |
| +struct IsCapturelessLambda<Lambda, void_t<decltype(&Lambda::operator())>> |
| + : std::is_convertible<Lambda, ExtractLambdaRunType<Lambda>*> {}; |
| + |
| // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw |
| // pointer to a RefCounted type. |
| // Implementation note: This non-specialized case handles zero-arity case only. |
| @@ -76,14 +126,30 @@ struct ForceVoidReturn<R(Args...)> { |
| // FunctorTraits<> |
| // |
| // See description at top of file. |
| -template <typename Functor> |
| +template <typename Functor, typename SFINAE = void> |
| struct FunctorTraits; |
| +// For captureless lambdas. |
| +template <typename Lambda> |
| +struct FunctorTraits< |
| + Lambda, typename std::enable_if<IsCapturelessLambda<Lambda>::value>::type> { |
| + using RunType = ExtractLambdaRunType<Lambda>; |
| + static constexpr bool is_method = false; |
| + static constexpr bool is_nullable = false; |
| + |
| + template <typename... RunArgs> |
| + static typename std::result_of<Lambda(RunArgs&&...)>::type |
| + Invoke(const Lambda& lambda, RunArgs&&... args) { |
| + return lambda(std::forward<RunArgs>(args)...); |
| + } |
| +}; |
| + |
| // For functions. |
| template <typename R, typename... Args> |
| struct FunctorTraits<R (*)(Args...)> { |
| using RunType = R(Args...); |
| static constexpr bool is_method = false; |
| + static constexpr bool is_nullable = true; |
| template <typename... RunArgs> |
| static R Invoke(R (*function)(Args...), RunArgs&&... args) { |
| @@ -98,6 +164,7 @@ template <typename R, typename... Args> |
| struct FunctorTraits<R(__stdcall*)(Args...)> { |
| using RunType = R(Args...); |
| static constexpr bool is_method = false; |
| + static constexpr bool is_nullable = true; |
| template <typename... RunArgs> |
| static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) { |
| @@ -110,6 +177,7 @@ template <typename R, typename... Args> |
| struct FunctorTraits<R(__fastcall*)(Args...)> { |
| using RunType = R(Args...); |
| static constexpr bool is_method = false; |
| + static constexpr bool is_nullable = true; |
| template <typename... RunArgs> |
| static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) { |
| @@ -124,6 +192,7 @@ template <typename R, typename Receiver, typename... Args> |
| struct FunctorTraits<R (Receiver::*)(Args...)> { |
| using RunType = R(Receiver*, Args...); |
| static constexpr bool is_method = true; |
| + static constexpr bool is_nullable = true; |
| template <typename ReceiverPtr, typename... RunArgs> |
| static R Invoke(R (Receiver::*method)(Args...), |
| @@ -143,6 +212,7 @@ template <typename R, typename Receiver, typename... Args> |
| struct FunctorTraits<R (Receiver::*)(Args...) const> { |
| using RunType = R(const Receiver*, Args...); |
| static constexpr bool is_method = true; |
| + static constexpr bool is_nullable = true; |
| template <typename ReceiverPtr, typename... RunArgs> |
| static R Invoke(R (Receiver::*method)(Args...) const, |
| @@ -176,6 +246,7 @@ template <typename R, typename... Args, CopyMode copy_mode> |
| struct FunctorTraits<Callback<R(Args...), copy_mode>> { |
| using RunType = R(Args...); |
| static constexpr bool is_method = false; |
| + static constexpr bool is_nullable = true; |
| template <typename CallbackType, typename... RunArgs> |
| static R Invoke(CallbackType&& callback, RunArgs&&... args) { |
| @@ -281,6 +352,17 @@ struct MakeUnboundRunTypeImpl { |
| using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>; |
| using Type = MakeFunctionType<ReturnType, UnboundArgs>; |
| }; |
| +template <typename Functor> |
| +typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type |
| +IsNull(const Functor& functor) { |
| + return !functor; |
| +} |
| + |
| +template <typename Functor> |
| +typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type |
| +IsNull(const Functor&) { |
| + return false; |
| +} |
| // BindState<> |
| // |
| @@ -292,7 +374,7 @@ struct BindState final : BindStateBase { |
| : BindStateBase(&Destroy), |
| functor_(std::move(functor)), |
| bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) { |
| - DCHECK(functor_); |
| + DCHECK(!IsNull(functor_)); |
| } |
| Functor functor_; |