| Index: base/bind_internal.h
|
| diff --git a/base/bind_internal.h b/base/bind_internal.h
|
| index 6b692a85a9d5424231489d964226d38f5b5932da..41c34ffea3c704f3054ade3aca889bdbd470082c 100644
|
| --- a/base/bind_internal.h
|
| +++ b/base/bind_internal.h
|
| @@ -46,6 +46,60 @@ 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 the original version, we need |make_void| as a helper struct to 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 Callable,
|
| + typename Signature = decltype(&Callable::operator())>
|
| +struct ExtractCallableRunTypeImpl;
|
| +
|
| +template <typename Callable, typename R, typename... Args>
|
| +struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> {
|
| + using Type = R(Args...);
|
| +};
|
| +
|
| +// Evaluated to RunType of the given callable type.
|
| +// Example:
|
| +// auto f = [](int, char*) { return 0.1; };
|
| +// ExtractCallableRunType<decltype(f)>
|
| +// is evaluated to
|
| +// double(int, char*);
|
| +template <typename Callable>
|
| +using ExtractCallableRunType =
|
| + typename ExtractCallableRunTypeImpl<Callable>::Type;
|
| +
|
| +// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator()
|
| +// and convertible to the corresponding function pointer. Otherwise, it's
|
| +// std::false_type.
|
| +// Example:
|
| +// IsConvertibleToRunType<void(*)()>::value is false.
|
| +//
|
| +// struct Foo {};
|
| +// IsConvertibleToRunType<void(Foo::*)()>::value is false.
|
| +//
|
| +// auto f = []() {};
|
| +// IsConvertibleToRunType<decltype(f)>::value is true.
|
| +//
|
| +// int i = 0;
|
| +// auto g = [i]() {};
|
| +// IsConvertibleToRunType<decltype(g)>::value is false.
|
| +template <typename Functor, typename SFINAE = void>
|
| +struct IsConvertibleToRunType : std::false_type {};
|
| +
|
| +template <typename Callable>
|
| +struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
|
| + : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
|
| +
|
| // 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 +130,34 @@ struct ForceVoidReturn<R(Args...)> {
|
| // FunctorTraits<>
|
| //
|
| // See description at top of file.
|
| -template <typename Functor>
|
| +template <typename Functor, typename SFINAE = void>
|
| struct FunctorTraits;
|
|
|
| +// For a callable type that is convertible to the corresponding function type.
|
| +// This specialization is intended to allow binding captureless lambdas by
|
| +// base::Bind(), based on the fact that captureless lambdas can be convertible
|
| +// to the function type while capturing lambdas can't.
|
| +template <typename Functor>
|
| +struct FunctorTraits<
|
| + Functor,
|
| + typename std::enable_if<IsConvertibleToRunType<Functor>::value>::type> {
|
| + using RunType = ExtractCallableRunType<Functor>;
|
| + static constexpr bool is_method = false;
|
| + static constexpr bool is_nullable = false;
|
| +
|
| + template <typename... RunArgs>
|
| + static ExtractReturnType<RunType>
|
| + Invoke(const Functor& functor, RunArgs&&... args) {
|
| + return functor(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 +172,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 +185,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 +200,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 +220,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 +254,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 +360,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 +382,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_;
|
|
|