diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-24 02:02:17 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-24 02:02:17 +0000 |
commit | c18b1056be790c55f10e407a1f6a3706bff7df03 (patch) | |
tree | 7ed333791fc8dfeaef29c07307e8efcfa1b44fba | |
parent | b2e900f755ea4e66b5f41413716ecb55720e354d (diff) | |
download | chromium_src-c18b1056be790c55f10e407a1f6a3706bff7df03.zip chromium_src-c18b1056be790c55f10e407a1f6a3706bff7df03.tar.gz chromium_src-c18b1056be790c55f10e407a1f6a3706bff7df03.tar.bz2 |
Callback support for unbound reference and array arguments.
Because the callback object uses const An& for the type of the Run() function in argument forwarding, the code breaks for An=T& or An=T[]. This CL adds in code to modify the parameter type to remove duplicate references, and other fun.
BUG=35223
TEST=new unittests
Review URL: http://codereview.chromium.org/6718021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79239 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/bind_helpers.h | 43 | ||||
-rw-r--r-- | base/bind_internal.h | 795 | ||||
-rw-r--r-- | base/bind_internal.h.pump | 67 | ||||
-rw-r--r-- | base/bind_internal_win.h | 55 | ||||
-rw-r--r-- | base/bind_internal_win.h.pump | 20 | ||||
-rw-r--r-- | base/bind_unittest.cc | 38 | ||||
-rw-r--r-- | base/callback.h | 100 | ||||
-rw-r--r-- | base/callback.h.pump | 8 | ||||
-rw-r--r-- | base/callback_internal.h | 46 |
9 files changed, 648 insertions, 524 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h index c1ca3d7..92194e7 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -161,7 +161,11 @@ struct UnsafeBindtoRefCountedArgHelper<true, T> }; template <typename T> -struct UnsafeBindtoRefCountedArg +struct UnsafeBindtoRefCountedArg : false_type { +}; + +template <typename T> +struct UnsafeBindtoRefCountedArg<T*> : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { }; @@ -233,43 +237,6 @@ struct MaybeRefcount<base::true_type, const T*> { static void Release(const T* o) { o->Release(); } }; - -// This is a typetraits object that's used to convert an argument type into a -// type suitable for storage. In particular, it strips off references, and -// converts arrays to pointers. -// -// This array type becomes an issue because we are passing bound parameters by -// const reference. In this case, we end up passing an actual array type in the -// initializer list which C++ does not allow. This will break passing of -// C-string literals. -template <typename T> -struct BindType { - typedef T StorageType; -}; - -// This should almost be impossible to trigger unless someone manually -// specifies type of the bind parameters. However, in case they do, -// this will guard against us accidentally storing a reference parameter. -template <typename T> -struct BindType<T&> { - typedef T StorageType; -}; - -// Note that for array types, we implicitly add a const in the conversion. This -// means that it is not possible to bind array arguments to functions that take -// a non-const pointer. Trying to specialize the template based on a "const -// T[n]" does not seem to match correctly, so we are stuck with this -// restriction. -template <typename T, size_t n> -struct BindType<T[n]> { - typedef const T* StorageType; -}; - -template <typename T> -struct BindType<T[]> { - typedef const T* StorageType; -}; - } // namespace internal template <typename T> diff --git a/base/bind_internal.h b/base/bind_internal.h index bb5f46f..606e2b0 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -3,6 +3,7 @@ // DO NOT EDIT BY HAND!!! + // 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. @@ -73,6 +74,7 @@ template <typename R> struct FunctionTraits<R(*)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + }; // Method: Arity 0. @@ -80,6 +82,10 @@ template <typename R, typename T> struct FunctionTraits<R(T::*)()> { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + }; // Const Method: Arity 0. @@ -87,6 +93,10 @@ template <typename R, typename T> struct FunctionTraits<R(T::*)() const> { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + }; // Function: Arity 1. @@ -94,6 +104,9 @@ template <typename R, typename X1> struct FunctionTraits<R(*)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + }; // Method: Arity 1. @@ -101,6 +114,11 @@ template <typename R, typename T, typename X1> struct FunctionTraits<R(T::*)(X1)> { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + }; // Const Method: Arity 1. @@ -108,6 +126,11 @@ template <typename R, typename T, typename X1> struct FunctionTraits<R(T::*)(X1) const> { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + }; // Function: Arity 2. @@ -115,6 +138,10 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(*)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + }; // Method: Arity 2. @@ -122,6 +149,12 @@ template <typename R, typename T, typename X1, typename X2> struct FunctionTraits<R(T::*)(X1, X2)> { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + }; // Const Method: Arity 2. @@ -129,6 +162,12 @@ template <typename R, typename T, typename X1, typename X2> struct FunctionTraits<R(T::*)(X1, X2) const> { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + }; // Function: Arity 3. @@ -136,6 +175,11 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + }; // Method: Arity 3. @@ -143,6 +187,13 @@ template <typename R, typename T, typename X1, typename X2, typename X3> struct FunctionTraits<R(T::*)(X1, X2, X3)> { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + }; // Const Method: Arity 3. @@ -150,6 +201,13 @@ template <typename R, typename T, typename X1, typename X2, typename X3> struct FunctionTraits<R(T::*)(X1, X2, X3) const> { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + }; // Function: Arity 4. @@ -157,6 +215,12 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + }; // Method: Arity 4. @@ -165,6 +229,14 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + }; // Const Method: Arity 4. @@ -173,6 +245,14 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + }; // Function: Arity 5. @@ -181,6 +261,13 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + }; // Method: Arity 5. @@ -189,6 +276,15 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + }; // Const Method: Arity 5. @@ -197,6 +293,15 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + }; // Function: Arity 6. @@ -205,6 +310,14 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + typedef X6 B6; + }; // Method: Arity 6. @@ -213,6 +326,16 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + typedef X6 B7; + }; // Const Method: Arity 6. @@ -221,6 +344,16 @@ template <typename R, typename T, typename X1, typename X2, typename X3, 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; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + typedef X6 B7; + }; // InvokerN<> @@ -258,11 +391,8 @@ struct Invoker0<StorageType, R(*)()> { // Function: Arity 1 -> 1. template <typename StorageType, typename R,typename X1> struct Invoker0<StorageType, R(*)(X1)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1); } @@ -271,12 +401,9 @@ struct Invoker0<StorageType, R(*)(X1)> { // Function: Arity 2 -> 2. template <typename StorageType, typename R,typename X1, typename X2> struct Invoker0<StorageType, R(*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2); } @@ -286,14 +413,10 @@ struct Invoker0<StorageType, R(*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker0<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3) { + static R 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); return invoker->f_(x1, x2, x3); } @@ -303,15 +426,11 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4) { + static R 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); return invoker->f_(x1, x2, x3, x4); } @@ -321,16 +440,12 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4, const X5& x5) { + static R 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); return invoker->f_(x1, x2, x3, x4, x5); } @@ -340,17 +455,13 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4, const X5& x5, const X6& x6) { + static R 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, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2, x3, x4, x5, x6); } @@ -362,10 +473,6 @@ struct Invoker1; // Function: Arity 1 -> 0. template <typename StorageType, typename R,typename X1> struct Invoker1<StorageType, R(*)(X1)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_)); @@ -384,12 +491,8 @@ struct Invoker1<StorageType, R(T::*)()> { // Function: Arity 2 -> 1. template <typename StorageType, typename R,typename X1, typename X2> struct Invoker1<StorageType, R(*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2); } @@ -398,11 +501,8 @@ 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1); } @@ -412,13 +512,9 @@ struct Invoker1<StorageType, R(T::*)(X1)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker1<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2, x3); } @@ -428,12 +524,9 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R, typename T, typename X1, typename X2> struct Invoker1<StorageType, R(T::*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2); } @@ -443,15 +536,10 @@ struct Invoker1<StorageType, R(T::*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4) { + static R 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); return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4); } @@ -461,14 +549,10 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3) { + static R 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); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3); } @@ -478,16 +562,11 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4, const X5& x5) { + static R 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); return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5); } @@ -497,15 +576,11 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4) { + static R 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); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4); } @@ -515,17 +590,12 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4, const X5& x5, const X6& x6) { + static R 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, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5, x6); } @@ -535,16 +605,12 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4, const X5& x5) { + static R 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); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4, x5); } @@ -556,11 +622,6 @@ struct Invoker2; // Function: Arity 2 -> 0. template <typename StorageType, typename R,typename X1, typename X2> struct Invoker2<StorageType, R(*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_)); @@ -570,10 +631,6 @@ 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_)); @@ -584,13 +641,8 @@ struct Invoker2<StorageType, R(T::*)(X1)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker2<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3); } @@ -600,12 +652,8 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R, typename T, typename X1, typename X2> struct Invoker2<StorageType, R(T::*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2); } @@ -615,14 +663,9 @@ struct Invoker2<StorageType, R(T::*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4); } @@ -632,13 +675,9 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3); } @@ -648,16 +687,10 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4, - const X5& x5) { + static R 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); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5); } @@ -667,15 +700,10 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4) { + static R 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); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4); @@ -686,17 +714,11 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4, - const X5& x5, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5, x6); @@ -707,16 +729,11 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4, const X5& x5) { + static R 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); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4, x5); @@ -730,12 +747,6 @@ struct Invoker3; template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker3<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -747,11 +758,6 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R, typename T, typename X1, typename X2> struct Invoker3<StorageType, R(T::*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -763,14 +769,8 @@ struct Invoker3<StorageType, R(T::*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), x4); @@ -781,13 +781,8 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3); @@ -798,15 +793,9 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), x4, x5); @@ -817,14 +806,9 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, x4); @@ -835,17 +819,10 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5, - const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), x4, x5, x6); @@ -856,16 +833,10 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4, - const X5& x5) { + static R 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); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, x4, x5); @@ -879,13 +850,6 @@ struct Invoker4; template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -897,12 +861,6 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -914,15 +872,8 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5); @@ -933,14 +884,8 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4); @@ -951,16 +896,9 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X5& x5, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5, x6); @@ -971,15 +909,9 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4, x5); @@ -993,14 +925,6 @@ struct Invoker5; template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -1012,13 +936,6 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -1030,16 +947,8 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x6); @@ -1050,15 +959,8 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5); @@ -1072,15 +974,6 @@ struct Invoker6; 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -1093,14 +986,6 @@ struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { 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)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -1133,6 +1018,7 @@ class InvokerStorage0 : public InvokerStorageBase { typedef typename TargetTraits::IsMethod IsMethod; + InvokerStorage0(Sig f) : f_(f) { } @@ -1149,6 +1035,7 @@ class InvokerStorage1 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker1<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // 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 // disallow binding of an array as the method's target object. @@ -1158,9 +1045,18 @@ class InvokerStorage1 : public InvokerStorageBase { COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, first_bound_argument_to_method_cannot_be_array); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage1(Sig f, const P1& p1) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1169,7 +1065,7 @@ class InvokerStorage1 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; + typename ParamTraits<P1>::StorageType p1_; }; template <typename Sig, typename P1, typename P2> @@ -1179,6 +1075,7 @@ class InvokerStorage2 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker2<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // 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 // disallow binding of an array as the method's target object. @@ -1190,10 +1087,20 @@ class InvokerStorage2 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value, p2_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage2(Sig f, const P1& p1, const P2& p2) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1202,8 +1109,8 @@ class InvokerStorage2 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; }; template <typename Sig, typename P1, typename P2, typename P3> @@ -1213,6 +1120,7 @@ class InvokerStorage3 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker3<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // 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 // disallow binding of an array as the method's target object. @@ -1226,11 +1134,22 @@ class InvokerStorage3 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value, p3_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1239,9 +1158,9 @@ class InvokerStorage3 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; }; template <typename Sig, typename P1, typename P2, typename P3, typename P4> @@ -1251,6 +1170,7 @@ class InvokerStorage4 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker4<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // 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 // disallow binding of an array as the method's target object. @@ -1266,12 +1186,24 @@ class InvokerStorage4 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value, p4_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value || + is_non_const_reference<typename TargetTraits::B4>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage4(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)), - p4_(static_cast<typename BindType<P4>::StorageType>(p4)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), + p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1280,10 +1212,10 @@ class InvokerStorage4 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; - typename BindType<P4>::StorageType p4_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; + typename ParamTraits<P4>::StorageType p4_; }; template <typename Sig, typename P1, typename P2, typename P3, typename P4, @@ -1294,6 +1226,7 @@ class InvokerStorage5 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker5<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // 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 // disallow binding of an array as the method's target object. @@ -1311,14 +1244,27 @@ class InvokerStorage5 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value, p5_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value || + is_non_const_reference<typename TargetTraits::B4>::value || + is_non_const_reference<typename TargetTraits::B5>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage5(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)), - p4_(static_cast<typename BindType<P4>::StorageType>(p4)), - p5_(static_cast<typename BindType<P5>::StorageType>(p5)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), + p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)), + p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1327,11 +1273,11 @@ class InvokerStorage5 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; - typename BindType<P4>::StorageType p4_; - typename BindType<P5>::StorageType p5_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; + typename ParamTraits<P4>::StorageType p4_; + typename ParamTraits<P5>::StorageType p5_; }; template <typename Sig, typename P1, typename P2, typename P3, typename P4, @@ -1342,6 +1288,7 @@ class InvokerStorage6 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker6<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // 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 // disallow binding of an array as the method's target object. @@ -1361,15 +1308,29 @@ class InvokerStorage6 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P6>::value, p6_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value || + is_non_const_reference<typename TargetTraits::B4>::value || + is_non_const_reference<typename TargetTraits::B5>::value || + is_non_const_reference<typename TargetTraits::B6>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage6(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)), - p4_(static_cast<typename BindType<P4>::StorageType>(p4)), - p5_(static_cast<typename BindType<P5>::StorageType>(p5)), - p6_(static_cast<typename BindType<P6>::StorageType>(p6)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), + p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)), + p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)), + p6_(static_cast<typename ParamTraits<P6>::StorageType>(p6)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1378,12 +1339,12 @@ class InvokerStorage6 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; - typename BindType<P4>::StorageType p4_; - typename BindType<P5>::StorageType p5_; - typename BindType<P6>::StorageType p6_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; + typename ParamTraits<P4>::StorageType p4_; + typename ParamTraits<P5>::StorageType p5_; + typename ParamTraits<P6>::StorageType p6_; }; } // namespace internal diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 84fb2ef..4ccec5e 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -82,6 +82,17 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + +$if ARITY > 0 [[ + + // Target type for each bound parameter. + +$for ARG [[ + typedef X$(ARG) B$(ARG); + +]] $$ for ARG +]] $$ if ARITY > 0 + }; // Method: Arity $(ARITY). @@ -90,6 +101,15 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + +$for ARG [[ + typedef X$(ARG) B$(ARG + 1); + +]] $$ for ARG + }; // Const Method: Arity $(ARITY). @@ -98,6 +118,15 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + +$for ARG [[ + typedef X$(ARG) B$(ARG + 1); + +]] $$ for ARG + }; ]] $$for ARITY @@ -151,17 +180,9 @@ template <typename StorageType, typename R[[]] $if ARITY > 0 [[,]][[]] $for ARG , [[typename X$(ARG)]]> struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> { -$if ARITY > 0 [[ - - COMPILE_ASSERT( - !($for ARG || [[ is_non_const_reference<X$(ARG)>::value ]]), - do_not_bind_functions_with_nonconst_ref); - -]] - static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND != 0 [[, ]][[]] -$for UNBOUND_ARG , [[const X$(UNBOUND_ARG)& x$(UNBOUND_ARG)]]) { +$for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] $$ Add comma if there are both boudn and unbound args. @@ -176,17 +197,9 @@ $if BOUND > 0 [[ 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)]])> { -$if M_ARITY > 0 [[ - - COMPILE_ASSERT( - !($for M_ARG || [[ is_non_const_reference<X$(M_ARG)>::value ]]), - do_not_bind_functions_with_nonconst_ref); - -]] - static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND > 0 [[, ]][[]] -$for M_UNBOUND_ARG , [[const X$(M_UNBOUND_ARG)& x$(M_UNBOUND_ARG)]]) { +$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)([[]] $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] @@ -228,6 +241,7 @@ class InvokerStorage$(BOUND) : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + $for BOUND_ARG [[ $if BOUND_ARG == 1 [[ @@ -247,6 +261,19 @@ $if BOUND_ARG == 1 [[ ]] $$ $for BOUND_ARG +$if BOUND > 0 [[ + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BOUND_ARG)>::value ]]), + do_not_bind_functions_with_nonconst_ref); + +]] + InvokerStorage$(BOUND)(Sig f $if BOUND > 0 [[, ]] @@ -256,7 +283,7 @@ $if BOUND == 0 [[ { ]] $else [[ -, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename BindType<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] { +, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] { MaybeRefcount<IsMethod, P1>::AddRef(p1_); ]] @@ -273,7 +300,7 @@ $if BOUND > 0 [[ Sig f_; $for BOUND_ARG [[ - typename BindType<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_; + typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_; ]] }; diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h index dab8d51..976a4d7 100644 --- a/base/bind_internal_win.h +++ b/base/bind_internal_win.h @@ -3,6 +3,7 @@ // DO NOT EDIT BY HAND!!! + // 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. @@ -39,6 +40,8 @@ template <typename R, typename X1> struct FunctionTraits<R(__stdcall *)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; }; // __fastcall Function: Arity 1. @@ -46,6 +49,8 @@ template <typename R, typename X1> struct FunctionTraits<R(__fastcall *)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; }; // __stdcall Function: Arity 2. @@ -53,6 +58,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(__stdcall *)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; }; // __fastcall Function: Arity 2. @@ -60,6 +68,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(__fastcall *)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; }; // __stdcall Function: Arity 3. @@ -67,6 +78,10 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; }; // __fastcall Function: Arity 3. @@ -74,6 +89,10 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; }; // __stdcall Function: Arity 4. @@ -81,6 +100,11 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; }; // __fastcall Function: Arity 4. @@ -88,6 +112,11 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; }; // __stdcall Function: Arity 5. @@ -96,6 +125,12 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; }; // __fastcall Function: Arity 5. @@ -104,6 +139,12 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; }; // __stdcall Function: Arity 6. @@ -112,6 +153,13 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + typedef X6 B6; }; // __fastcall Function: Arity 6. @@ -120,6 +168,13 @@ 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; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + typedef X6 B6; }; } // namespace internal diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump index 4d213a3..06ceaca1 100644 --- a/base/bind_internal_win.h.pump +++ b/base/bind_internal_win.h.pump @@ -34,6 +34,16 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(__stdcall *)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + +$if ARITY > 0 [[ + + // Target type for each bound parameter. + +$for ARG [[ + typedef X$(ARG) B$(ARG); + +]] $$ for ARG +]] $$ if ARITY > 0 }; // __fastcall Function: Arity $(ARITY). @@ -42,6 +52,16 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(__fastcall *)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + +$if ARITY > 0 [[ + + // Target type for each bound parameter. + +$for ARG [[ + typedef X$(ARG) B$(ARG); + +]] $$ for ARG +]] $$ if ARITY > 0 }; ]] $$for ARITY diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index 061808b..b3e0160 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -174,6 +174,10 @@ int UnwrapNoRefParentConstRef(const NoRefParent& p) { return p.value; } +void RefArgSet(int &n) { + n = 2; +} + // Only useful in no-compile tests. int UnwrapNoRefParentRef(Parent& p) { return p.value; @@ -351,6 +355,37 @@ TEST_F(BindTest, ArgumentBinding) { EXPECT_EQ(8, bind_const_reference_promotes_cb.Run()); } +// Unbound argument type support tests. +// - Unbound value. +// - Unbound pointer. +// - Unbound reference. +// - Unbound const reference. +// - Unbound unsized array. +// - Unbound sized array. +// - Unbound array-of-arrays. +TEST_F(BindTest, UnboundArgumentTypeSupport) { + Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic1<int>); + Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic1<int*>); + Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic1<int&>); + Callback<void(const int&)> unbound_const_ref_cb = + Bind(&VoidPolymorphic1<const int&>); + Callback<void(int[])> unbound_unsized_array_cb = + Bind(&VoidPolymorphic1<int[]>); + Callback<void(int[2])> unbound_sized_array_cb = + Bind(&VoidPolymorphic1<int[2]>); + Callback<void(int[][2])> unbound_array_of_arrays_cb = + Bind(&VoidPolymorphic1<int[][2]>); +} + +// Function with unbound reference parameter. +// - Original paraemter is modified by callback. +TEST_F(BindTest, UnboundReferenceSupport) { + int n = 0; + Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet); + unbound_ref_cb.Run(n); + EXPECT_EQ(2, n); +} + // Functions that take reference parameters. // - Forced reference parameter type still stores a copy. // - Forced const reference parameter type still stores a copy. @@ -570,14 +605,13 @@ TEST_F(BindTest, NoCompile) { // // HasRef p[10]; // Callback<void(void)> method_bound_to_array_cb = - // Bind(&HasRef::VoidConstMethod0, p); + // Bind(&HasRef::VoidConstMethod0, p); // method_bound_to_array_cb.Run(); // - Refcounted types should not be bound as a raw pointer. // HasRef for_raw_ptr; // Callback<void(void)> ref_count_as_raw_ptr = // Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); - // ASSERT_EQ(&for_raw_ptr, ref_count_as_raw_ptr.Run()); } diff --git a/base/callback.h b/base/callback.h index bcc3dfd..2e17ae9 100644 --- a/base/callback.h +++ b/base/callback.h @@ -3,6 +3,7 @@ // DO NOT EDIT BY HAND!!! + // 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. @@ -225,7 +226,8 @@ class Callback; template <typename R> class Callback<R(void)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*); Callback() : CallbackBase(NULL, NULL) { } @@ -254,7 +256,9 @@ class Callback<R(void)> : public internal::CallbackBase { template <typename R, typename A1> class Callback<R(A1)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -272,7 +276,7 @@ class Callback<R(A1)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -283,8 +287,10 @@ class Callback<R(A1)> : public internal::CallbackBase { template <typename R, typename A1, typename A2> class Callback<R(A1, A2)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -302,8 +308,8 @@ class Callback<R(A1, A2)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -315,9 +321,11 @@ class Callback<R(A1, A2)> : public internal::CallbackBase { template <typename R, typename A1, typename A2, typename A3> class Callback<R(A1, A2, A3)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -335,9 +343,9 @@ class Callback<R(A1, A2, A3)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -350,10 +358,12 @@ class Callback<R(A1, A2, A3)> : public internal::CallbackBase { template <typename R, typename A1, typename A2, typename A3, typename A4> class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&, - const A4&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType, + typename internal::ParamTraits<A4>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -371,10 +381,10 @@ class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3, + typename internal::ParamTraits<A4>::ForwardType a4) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -389,11 +399,13 @@ template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5> class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&, - const A4&, - const A5&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType, + typename internal::ParamTraits<A4>::ForwardType, + typename internal::ParamTraits<A5>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -411,11 +423,11 @@ class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4, - const A5& a5) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3, + typename internal::ParamTraits<A4>::ForwardType a4, + typename internal::ParamTraits<A5>::ForwardType a5) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -431,12 +443,14 @@ template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&, - const A4&, - const A5&, - const A6&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType, + typename internal::ParamTraits<A4>::ForwardType, + typename internal::ParamTraits<A5>::ForwardType, + typename internal::ParamTraits<A6>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -454,12 +468,12 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4, - const A5& a5, - const A6& a6) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3, + typename internal::ParamTraits<A4>::ForwardType a4, + typename internal::ParamTraits<A5>::ForwardType a5, + typename internal::ParamTraits<A6>::ForwardType a6) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); diff --git a/base/callback.h.pump b/base/callback.h.pump index 34b0eb0..542a84f 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -240,10 +240,10 @@ class Callback<R($for ARG , [[A$(ARG)]])> : public internal::CallbackBase { ]] public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*[[]] + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*[[]] $if ARITY != 0 [[, ]] -$for ARG , - [[const A$(ARG)&]]); +$for ARG , [[typename internal::ParamTraits<A$(ARG)>::ForwardType]]); Callback() : CallbackBase(NULL, NULL) { } @@ -262,7 +262,7 @@ $for ARG , } R Run($for ARG , - [[const A$(ARG)& a$(ARG)]]) const { + [[typename internal::ParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); diff --git a/base/callback_internal.h b/base/callback_internal.h index 4f1d3c3..6b8fdff2 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h @@ -80,6 +80,52 @@ class CallbackBase { InvokeFuncStorage polymorphic_invoke_; }; +// This is a typetraits object that's used to take an argument type, and +// extract a suitable type for storing and forwarding arguments. +// +// In particular, it strips off references, and converts arrays to +// pointers for storage; and it avoids accidentally trying to create a +// "reference of a reference" if the argument is a reference type. +// +// This array type becomes an issue for storage because we are passing bound +// parameters by const reference. In this case, we end up passing an actual +// array type in the initializer list which C++ does not allow. This will +// break passing of C-string literals. +template <typename T> +struct ParamTraits { + typedef const T& ForwardType; + typedef T StorageType; +}; + +// The Storage should almost be impossible to trigger unless someone manually +// specifies type of the bind parameters. However, in case they do, +// this will guard against us accidentally storing a reference parameter. +// +// The ForwardType should only be used for unbound arguments. +template <typename T> +struct ParamTraits<T&> { + typedef T& ForwardType; + typedef T StorageType; +}; + +// Note that for array types, we implicitly add a const in the conversion. This +// means that it is not possible to bind array arguments to functions that take +// a non-const pointer. Trying to specialize the template based on a "const +// T[n]" does not seem to match correctly, so we are stuck with this +// restriction. +template <typename T, size_t n> +struct ParamTraits<T[n]> { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// See comment for ParamTraits<T[n]>. +template <typename T> +struct ParamTraits<T[]> { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + } // namespace internal } // namespace base |