diff options
-rw-r--r-- | base/bind_helpers.h | 9 | ||||
-rw-r--r-- | base/bind_internal.h | 569 | ||||
-rw-r--r-- | base/bind_internal.h.pump | 63 | ||||
-rw-r--r-- | base/bind_internal_win.h | 40 | ||||
-rw-r--r-- | base/bind_internal_win.h.pump | 4 | ||||
-rw-r--r-- | base/bind_unittest.cc | 52 | ||||
-rw-r--r-- | base/callback.h | 2 | ||||
-rw-r--r-- | base/callback.h.pump | 8 | ||||
-rw-r--r-- | base/template_util.h | 5 |
9 files changed, 676 insertions, 76 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h index 73fd81e..e4b4a17 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -52,6 +52,7 @@ #pragma once #include "base/basictypes.h" +#include "base/memory/weak_ptr.h" #include "base/template_util.h" namespace base { @@ -215,7 +216,7 @@ const T& Unwrap(ConstRefWrapper<T> const_ref) { // Utility for handling different refcounting semantics in the Bind() // function. -template <typename ref, typename T> +template <typename IsMethod, typename T> struct MaybeRefcount; template <typename T> @@ -248,6 +249,12 @@ struct MaybeRefcount<base::true_type, const T*> { static void Release(const T* o) { o->Release(); } }; +template <typename T> +struct MaybeRefcount<base::true_type, WeakPtr<T> > { + static void AddRef(const WeakPtr<T>&) {} + static void Release(const WeakPtr<T>&) {} +}; + } // namespace internal template <typename T> diff --git a/base/bind_internal.h b/base/bind_internal.h index 606e2b0..203a286 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -14,6 +14,7 @@ #include "base/bind_helpers.h" #include "base/callback_internal.h" +#include "base/memory/weak_ptr.h" #include "base/template_util.h" #include "build/build_config.h" @@ -39,10 +40,21 @@ namespace internal { // a calback. // InvokerStorageN<> -- Provides storage for the bound parameters, and // typedefs to the above. +// IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>. // // More details about the design of each class is included in a comment closer // to their defition. + +// IsWeakMethod determines if we are binding a method to a WeakPtr<> for an +// object. It is used to select an InvokerN that will no-op itself in the +// event the WeakPtr<> for the target object is invalidated. +template <bool IsMethod, typename T> +struct IsWeakMethod : public false_type {}; + +template <typename T> +struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; + // FunctionTraits<> // // The FunctionTraits<> template determines the type of function, and also @@ -75,6 +87,8 @@ struct FunctionTraits<R(*)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + typedef R Return; + }; // Method: Arity 0. @@ -83,6 +97,8 @@ struct FunctionTraits<R(T::*)()> { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -94,6 +110,8 @@ struct FunctionTraits<R(T::*)() const> { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -104,6 +122,9 @@ template <typename R, typename X1> struct FunctionTraits<R(*)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; @@ -115,6 +136,8 @@ struct FunctionTraits<R(T::*)(X1)> { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -127,6 +150,8 @@ struct FunctionTraits<R(T::*)(X1) const> { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -138,6 +163,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(*)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -150,6 +178,8 @@ struct FunctionTraits<R(T::*)(X1, X2)> { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -163,6 +193,8 @@ struct FunctionTraits<R(T::*)(X1, X2) const> { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -175,6 +207,9 @@ template <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(*)(X1, X2, X3)> { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -188,6 +223,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3)> { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -202,6 +239,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3) const> { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -215,6 +254,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(*)(X1, X2, X3, X4)> { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -230,6 +272,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -246,6 +290,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -261,6 +307,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(*)(X1, X2, X3, X4, X5)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -277,6 +326,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -294,6 +345,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -310,6 +363,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(*)(X1, X2, X3, X4, X5, X6)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -327,6 +383,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -345,6 +403,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -376,12 +436,12 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> { // templates classes in the system to only have as many specializations as // the max arity of function we wish to support. -template <typename StorageType, typename NormalizedSig> +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker0; // Function: Arity 0 -> 0. template <typename StorageType, typename R> -struct Invoker0<StorageType, R(*)()> { +struct Invoker0<false, StorageType, R(*)()> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(); @@ -390,7 +450,7 @@ struct Invoker0<StorageType, R(*)()> { // Function: Arity 1 -> 1. template <typename StorageType, typename R,typename X1> -struct Invoker0<StorageType, R(*)(X1)> { +struct Invoker0<false, StorageType, R(*)(X1)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); @@ -400,7 +460,7 @@ struct Invoker0<StorageType, R(*)(X1)> { // Function: Arity 2 -> 2. template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker0<StorageType, R(*)(X1, X2)> { +struct Invoker0<false, StorageType, R(*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2) { @@ -412,7 +472,7 @@ struct Invoker0<StorageType, R(*)(X1, X2)> { // Function: Arity 3 -> 3. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker0<StorageType, R(*)(X1, X2, X3)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -425,7 +485,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3)> { // Function: Arity 4 -> 4. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -439,7 +499,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { // Function: Arity 5 -> 5. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -454,7 +514,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Function: Arity 6 -> 6. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -467,12 +527,12 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { } }; -template <typename StorageType, typename NormalizedSig> +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker1; // Function: Arity 1 -> 0. template <typename StorageType, typename R,typename X1> -struct Invoker1<StorageType, R(*)(X1)> { +struct Invoker1<false, StorageType, R(*)(X1)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_)); @@ -481,16 +541,29 @@ struct Invoker1<StorageType, R(*)(X1)> { // Method: Arity 0 -> 0. template <typename StorageType, typename R, typename T> -struct Invoker1<StorageType, R(T::*)()> { +struct Invoker1<false, StorageType, R(T::*)()> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(); } }; +// WeakPtr Method: Arity 0 -> 0. +template <typename StorageType, typename T> +struct Invoker1<true, StorageType, void(T::*)()> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(); + } +}; + // Function: Arity 2 -> 1. template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker1<StorageType, R(*)(X1, X2)> { +struct Invoker1<false, StorageType, R(*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); @@ -500,7 +573,7 @@ struct Invoker1<StorageType, R(*)(X1, X2)> { // Method: Arity 1 -> 1. template <typename StorageType, typename R, typename T, typename X1> -struct Invoker1<StorageType, R(T::*)(X1)> { +struct Invoker1<false, StorageType, R(T::*)(X1)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); @@ -508,10 +581,24 @@ struct Invoker1<StorageType, R(T::*)(X1)> { } }; +// WeakPtr Method: Arity 1 -> 1. +template <typename StorageType, typename T, typename X1> +struct Invoker1<true, StorageType, void(T::*)(X1)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1); + } +}; + // Function: Arity 3 -> 2. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker1<StorageType, R(*)(X1, X2, X3)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3) { @@ -523,7 +610,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3)> { // Method: Arity 2 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2> -struct Invoker1<StorageType, R(T::*)(X1, X2)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2) { @@ -532,10 +619,25 @@ struct Invoker1<StorageType, R(T::*)(X1, X2)> { } }; +// WeakPtr Method: Arity 2 -> 2. +template <typename StorageType, typename T, typename X1, typename X2> +struct Invoker1<true, StorageType, void(T::*)(X1, X2)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2); + } +}; + // Function: Arity 4 -> 3. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -548,7 +650,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 3. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -558,10 +660,27 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 3. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3); + } +}; + // Function: Arity 5 -> 4. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -575,7 +694,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 4. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -586,10 +705,28 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 4. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3, x4); + } +}; + // Function: Arity 6 -> 5. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -604,7 +741,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 5. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -616,12 +753,31 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 5. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3, x4, x5); + } +}; + +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker2; // Function: Arity 2 -> 0. template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker2<StorageType, R(*)(X1, X2)> { +struct Invoker2<false, StorageType, R(*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_)); @@ -630,17 +786,30 @@ struct Invoker2<StorageType, R(*)(X1, X2)> { // Method: Arity 1 -> 0. template <typename StorageType, typename R, typename T, typename X1> -struct Invoker2<StorageType, R(T::*)(X1)> { +struct Invoker2<false, StorageType, R(T::*)(X1)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_)); } }; +// WeakPtr Method: Arity 1 -> 0. +template <typename StorageType, typename T, typename X1> +struct Invoker2<true, StorageType, void(T::*)(X1)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_)); + } +}; + // Function: Arity 3 -> 1. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker2<StorageType, R(*)(X1, X2, X3)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); @@ -651,7 +820,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3)> { // Method: Arity 2 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2> -struct Invoker2<StorageType, R(T::*)(X1, X2)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); @@ -659,10 +828,24 @@ struct Invoker2<StorageType, R(T::*)(X1, X2)> { } }; +// WeakPtr Method: Arity 2 -> 1. +template <typename StorageType, typename T, typename X1, typename X2> +struct Invoker2<true, StorageType, void(T::*)(X1, X2)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2); + } +}; + // Function: Arity 4 -> 2. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4) { @@ -674,7 +857,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3) { @@ -683,10 +866,26 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 2. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3); + } +}; + // Function: Arity 5 -> 3. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4, @@ -699,7 +898,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 3. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -710,10 +909,27 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 3. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4); + } +}; + // Function: Arity 6 -> 4. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4, @@ -728,7 +944,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 4. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -740,13 +956,31 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 4. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4, x5); + } +}; + +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker3; // Function: Arity 3 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker3<StorageType, R(*)(X1, X2, X3)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -757,7 +991,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3)> { // Method: Arity 2 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2> -struct Invoker3<StorageType, R(T::*)(X1, X2)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -765,10 +999,23 @@ struct Invoker3<StorageType, R(T::*)(X1, X2)> { } }; +// WeakPtr Method: Arity 2 -> 0. +template <typename StorageType, typename T, typename X1, typename X2> +struct Invoker3<true, StorageType, void(T::*)(X1, X2)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_)); + } +}; + // Function: Arity 4 -> 1. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); @@ -780,7 +1027,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); @@ -789,10 +1036,25 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 1. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3); + } +}; + // Function: Arity 5 -> 2. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4, typename internal::ParamTraits<X5>::ForwardType x5) { @@ -805,7 +1067,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4) { @@ -815,10 +1077,27 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 2. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, + x4); + } +}; + // Function: Arity 6 -> 3. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4, typename internal::ParamTraits<X5>::ForwardType x5, @@ -832,7 +1111,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 3. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4, @@ -843,13 +1122,31 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 3. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, + x4, x5); + } +}; + +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker4; // Function: Arity 4 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -860,7 +1157,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -868,10 +1165,25 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 0. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_)); + } +}; + // Function: Arity 5 -> 1. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); @@ -883,7 +1195,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); @@ -892,10 +1204,26 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 1. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), x4); + } +}; + // Function: Arity 6 -> 2. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X5>::ForwardType x5, typename internal::ParamTraits<X6>::ForwardType x6) { @@ -908,7 +1236,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4, typename internal::ParamTraits<X5>::ForwardType x5) { @@ -918,13 +1246,30 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 2. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), x4, x5); + } +}; + +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker5; // Function: Arity 5 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -935,7 +1280,7 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -943,10 +1288,25 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 0. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker5<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), Unwrap(invoker->p5_)); + } +}; + // Function: Arity 6 -> 1. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); @@ -958,7 +1318,7 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); @@ -967,13 +1327,29 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 1. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker5<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5); + } +}; + +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker6; // Function: Arity 6 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker6<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -985,7 +1361,7 @@ struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker6<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -994,6 +1370,20 @@ struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; +// WeakPtr Method: Arity 5 -> 0. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker6<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), Unwrap(invoker->p5_), Unwrap(invoker->p6_)); + } +}; // InvokerStorageN<> // @@ -1014,8 +1404,10 @@ class InvokerStorage0 : public InvokerStorageBase { public: typedef InvokerStorage0 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker0<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef Invoker0<false, StorageType, + typename TargetTraits::NormalizedSig> Invoker; @@ -1033,8 +1425,14 @@ class InvokerStorage1 : public InvokerStorageBase { public: typedef InvokerStorage1 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker1<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef Invoker1<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1073,8 +1471,15 @@ class InvokerStorage2 : public InvokerStorageBase { public: typedef InvokerStorage2 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker2<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef Invoker2<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1118,8 +1523,16 @@ class InvokerStorage3 : public InvokerStorageBase { public: typedef InvokerStorage3 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker3<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef Invoker3<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1168,8 +1581,17 @@ class InvokerStorage4 : public InvokerStorageBase { public: typedef InvokerStorage4 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker4<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef ParamTraits<P4> P4Traits; + typedef Invoker4<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1224,8 +1646,18 @@ class InvokerStorage5 : public InvokerStorageBase { public: typedef InvokerStorage5 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker5<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef ParamTraits<P4> P4Traits; + typedef ParamTraits<P5> P5Traits; + typedef Invoker5<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1286,8 +1718,19 @@ class InvokerStorage6 : public InvokerStorageBase { public: typedef InvokerStorage6 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker6<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef ParamTraits<P4> P4Traits; + typedef ParamTraits<P5> P5Traits; + typedef ParamTraits<P6> P6Traits; + typedef Invoker6<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 4ccec5e..85875de 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -17,6 +17,7 @@ $var MAX_ARITY = 6 #include "base/bind_helpers.h" #include "base/callback_internal.h" +#include "base/memory/weak_ptr.h" #include "base/template_util.h" #include "build/build_config.h" @@ -42,10 +43,21 @@ namespace internal { // a calback. // InvokerStorageN<> -- Provides storage for the bound parameters, and // typedefs to the above. +// IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>. // // More details about the design of each class is included in a comment closer // to their defition. + +// IsWeakMethod determines if we are binding a method to a WeakPtr<> for an +// object. It is used to select an InvokerN that will no-op itself in the +// event the WeakPtr<> for the target object is invalidated. +template <bool IsMethod, typename T> +struct IsWeakMethod : public false_type {}; + +template <typename T> +struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; + // FunctionTraits<> // // The FunctionTraits<> template determines the type of function, and also @@ -83,6 +95,8 @@ struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + typedef R Return; + $if ARITY > 0 [[ // Target type for each bound parameter. @@ -102,6 +116,8 @@ struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -119,6 +135,8 @@ struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -154,7 +172,7 @@ $for ARG [[ $range BOUND 0..MAX_ARITY $for BOUND [[ -template <typename StorageType, typename NormalizedSig> +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker$(BOUND); $range ARITY 0..MAX_ARITY @@ -179,7 +197,7 @@ $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY template <typename StorageType, typename R[[]] $if ARITY > 0 [[,]][[]] $for ARG , [[typename X$(ARG)]]> -struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> { +struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> { static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND != 0 [[, ]][[]] $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) { @@ -196,7 +214,7 @@ $if BOUND > 0 [[ // Method: Arity $(M_ARITY) -> $(UNBOUND). template <typename StorageType, typename R, typename T[[]] $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> -struct Invoker$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { +struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND > 0 [[, ]][[]] $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) { @@ -208,13 +226,31 @@ $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); } }; +// WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND). +template <typename StorageType, typename T[[]] +$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> +struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]])> { + static void DoInvoke(InvokerStorageBase* base[[]] +$if UNBOUND > 0 [[, ]][[]] +$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)([[]] +$for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] +$if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]] +$for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); + } +}; + ]] $$ if BOUND ]] $$ if UNBOUND ]] $$ for ARITY ]] $$ for BOUND - // InvokerStorageN<> // // These are the actual storage classes for the Invokers. @@ -239,8 +275,25 @@ class InvokerStorage$(BOUND) : public InvokerStorageBase { public: typedef InvokerStorage$(BOUND) StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + +$for BOUND_ARG [[ + typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits; + +]] + +$if BOUND == 0 [[ + typedef Invoker$(BOUND)<false, StorageType, + typename TargetTraits::NormalizedSig> Invoker; +]] $else [[ + typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); +]] + $for BOUND_ARG [[ $if BOUND_ARG == 1 [[ diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h index 85ba2ae..250f472 100644 --- a/base/bind_internal_win.h +++ b/base/bind_internal_win.h @@ -31,6 +31,8 @@ template <typename R> struct FunctionTraits<R(__stdcall *)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + + typedef R Return; }; // __fastcall Function: Arity 0. @@ -38,6 +40,8 @@ template <typename R> struct FunctionTraits<R(__fastcall *)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + + typedef R Return; }; // __stdcall Function: Arity 1. @@ -45,6 +49,9 @@ template <typename R, typename X1> struct FunctionTraits<R(__stdcall *)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; }; @@ -54,6 +61,9 @@ template <typename R, typename X1> struct FunctionTraits<R(__fastcall *)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; }; @@ -63,6 +73,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(__stdcall *)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -73,6 +86,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(__fastcall *)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -83,6 +99,9 @@ template <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(__stdcall *)(X1, X2, X3)> { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -94,6 +113,9 @@ template <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(__fastcall *)(X1, X2, X3)> { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -105,6 +127,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4)> { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -117,6 +142,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4)> { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -130,6 +158,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -144,6 +175,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -158,6 +192,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5, X6)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -173,6 +210,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5, X6)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump index d293fcc..80ee37d 100644 --- a/base/bind_internal_win.h.pump +++ b/base/bind_internal_win.h.pump @@ -40,6 +40,8 @@ struct FunctionTraits<R(__stdcall *)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + typedef R Return; + $if ARITY > 0 [[ // Target type for each bound parameter. @@ -58,6 +60,8 @@ struct FunctionTraits<R(__fastcall *)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + typedef R Return; + $if ARITY > 0 [[ // Target type for each bound parameter. diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index c131a86..d57f3d0 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -183,6 +183,10 @@ void RefArgSet(int &n) { n = 2; } +int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) { + return n; +} + // Only useful in no-compile tests. int UnwrapNoRefParentRef(Parent& p) { return p.value; @@ -451,7 +455,7 @@ TEST_F(BindTest, SupportsAddRefAndRelease) { } // Unretained() wrapper support. -// - Method bound to Unretained() non-object. +// - Method bound to Unretained() non-const object. // - Const method bound to Unretained() non-const object. // - Const method bound to Unretained() const object. TEST_F(BindTest, Unretained) { @@ -471,6 +475,46 @@ TEST_F(BindTest, Unretained) { const_method_const_ptr_cb.Run(); } +// WeakPtr() support. +// - Method bound to WeakPtr<> to non-const object. +// - Const method bound to WeakPtr<> to non-const object. +// - Const method bound to WeakPtr<> to const object. +// - Normal Function with WeakPtr<> as P1 can have return type and is +// not canceled. +TEST_F(BindTest, WeakPtr) { + EXPECT_CALL(no_ref_, VoidMethod0()); + EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2); + + WeakPtrFactory<NoRef> weak_factory(&no_ref_); + WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); + + Callback<void(void)> method_cb = + Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); + method_cb.Run(); + + Callback<void(void)> const_method_cb = + Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); + const_method_cb.Run(); + + Callback<void(void)> const_method_const_ptr_cb = + Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); + const_method_const_ptr_cb.Run(); + + Callback<int(int)> normal_func_cb = + Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr()); + EXPECT_EQ(1, normal_func_cb.Run(1)); + + weak_factory.InvalidateWeakPtrs(); + const_weak_factory.InvalidateWeakPtrs(); + + method_cb.Run(); + const_method_cb.Run(); + const_method_const_ptr_cb.Run(); + + // Still runs even after the pointers are invalidated. + EXPECT_EQ(2, normal_func_cb.Run(2)); +} + // ConstRef() wrapper support. // - Binding w/o ConstRef takes a copy. // - Binding a ConstRef takes a reference. @@ -627,6 +671,12 @@ TEST_F(BindTest, NoCompile) { // Callback<void(void)> ref_count_as_raw_ptr = // Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); + // - WeakPtrs cannot be bound to methods with return types. + // HasRef for_raw_ptr; + // WeakPtrFactory<NoRef> weak_factory(&no_ref_); + // Callback<int(void)> weak_ptr_with_non_void_return_type = + // Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr()); + } #if defined(OS_WIN) diff --git a/base/callback.h b/base/callback.h index 983fa7b02..fbd81d8 100644 --- a/base/callback.h +++ b/base/callback.h @@ -49,7 +49,7 @@ // // void PrintHi() { LOG(INFO) << "hi."; } // base::Closure void_func_cb = base::Bind(&PrintHi); -// LOG(INFO) << void_func_cb.Run(); // Prints: hi. +// void_func_cb.Run(); // Prints: hi. // // /* Binding a class method. */ // class Ref : public RefCountedThreadSafe<Ref> { diff --git a/base/callback.h.pump b/base/callback.h.pump index b565e38..cc45dd7 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -47,12 +47,12 @@ $var MAX_ARITY = 6 // // /* Binding a normal function. */ // int Return5() { return 5; } -// base::Callback<int(int)> func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(5); // Prints 5. +// base::Callback<int(void)> func_cb = base::Bind(&Return5); +// LOG(INFO) << func_cb.Run(); // Prints 5. // // void PrintHi() { LOG(INFO) << "hi."; } // base::Closure void_func_cb = base::Bind(&PrintHi); -// LOG(INFO) << void_func_cb.Run(); // Prints: hi. +// void_func_cb.Run(); // Prints: hi. // // /* Binding a class method. */ // class Ref : public RefCountedThreadSafe<Ref> { @@ -191,7 +191,7 @@ $var MAX_ARITY = 6 // // These are not features that are required in Chromium. Some of them, such as // allowing for reference parameters, and subtyping of functions, may actually -// because a source of errors. Removing support for these features actually +// become a source of errors. Removing support for these features actually // allows for a simpler implementation, and a terser Currying API. // // diff --git a/base/template_util.h b/base/template_util.h index e48af91..66e6a61 100644 --- a/base/template_util.h +++ b/base/template_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -37,6 +37,9 @@ template <class T> struct is_non_const_reference : false_type {}; template <class T> struct is_non_const_reference<T&> : true_type {}; template <class T> struct is_non_const_reference<const T&> : false_type {}; +template <class T> struct is_void : false_type {}; +template <> struct is_void<void> : true_type {}; + namespace internal { // Types YesType and NoType are guaranteed such that sizeof(YesType) < |