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_; |