From 35e29f15a88efef6e4ddcdf8dd41a38646cff1e2 Mon Sep 17 00:00:00 2001 From: Pavol Marko Date: Fri, 14 Oct 2005 20:57:43 +0000 Subject: [PATCH] Faluco added new FastDelegate version, added more tests to testreentr --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40135 --- sourcehook/FastDelegate.h | 715 +++++++++++++++++++++------ sourcehook/generate/FastDelegate.h | 715 +++++++++++++++++++++------ sourcehook/generate/FastDelegate.hxx | 95 +++- sourcehook/test/testreentr.cpp | 266 +++++++++- 4 files changed, 1474 insertions(+), 317 deletions(-) diff --git a/sourcehook/FastDelegate.h b/sourcehook/FastDelegate.h index 1b45fe0..5a02808 100644 --- a/sourcehook/FastDelegate.h +++ b/sourcehook/FastDelegate.h @@ -5,7 +5,7 @@ // - Don Clugston, Mar 2004. // Major contributions were made by Jody Hagins. // History: -// 24-Apr-04 1.0 Submitted to CodeProject. +// 24-Apr-04 1.0 * Submitted to CodeProject. // 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. // * Improved syntax for horrible_cast (thanks Paul Bludov). // * Tested on Metrowerks MWCC and Intel ICL (IA32) @@ -30,14 +30,20 @@ // * Less use of macros. Error messages should be more comprehensible. // * Added include guards // * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). -// * Now tested on VS 2005 Beta, PGI C++ +// * Now tested on VS 2005 Express Beta, PGI C++ // 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. // * <,>,<=,>= comparison operators to allow storage in ordered containers. // * Substantial reduction of code size, especially the 'Closure' class. // * Standardised all the compiler-specific workarounds. // * MFP conversion now works for CodePlay (but not yet supported in the full code). -// * Now compiles without warnings on _any_ compiler, including BCC 5.5.1 +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 // * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. #ifndef FASTDELEGATE_H #define FASTDELEGATE_H @@ -531,8 +537,10 @@ struct SimplifyMemFunc // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ // | 0 | 0 | 0 | Empty | // | !=0 |(dontcare)| Invoker | Static function| -// | 0 | !=0 | !=0 | Method call | +// | 0 | !=0 | !=0* | Method call | // +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). // When stored stored inside a specific delegate, the 'dontcare' entries are replaced // with a reference to the delegate itself. This complicates the = and == operators // for the delegate class. @@ -544,9 +552,11 @@ struct SimplifyMemFunc // horrible_cast. In this case the DelegateMemento implementation is simple: // +--pThis --+-- pMemFunc-+-- Meaning---------------------+ // | 0 | 0 | Empty | -// | !=0 | !=0 | Static function or method call| +// | !=0 | !=0* | Static function or method call| // +----------+------------+-------------------------------+ -// Note that the Sun C++ and MSVC documentation explicitly state that they +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they // support static_cast between void * and function pointers. class DelegateMemento { @@ -570,9 +580,7 @@ public: } #else DelegateMemento() : m_pthis(0), m_pFunction(0) {}; - void clear() { - m_pthis=0; m_pFunction=0; - } + void clear() { m_pthis=0; m_pFunction=0; } #endif public: #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) @@ -603,8 +611,13 @@ public: return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! inline bool operator ! () const // Is it bound to anything? - { return m_pFunction==0; } + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } public: DelegateMemento & operator = (const DelegateMemento &right) { SetMementoFrom(right); @@ -723,7 +736,11 @@ public: template < class DerivedClass, class ParentInvokerSig > inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, StaticFuncPtr function_to_bind ) { - bindmemfunc(pParent, static_function_invoker); + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } m_pStaticFunction=reinterpret_cast(function_to_bind); } inline UnvoidStaticFuncPtr GetStaticFunction() const { @@ -752,9 +769,13 @@ public: template < class DerivedClass, class ParentInvokerSig> inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, StaticFuncPtr function_to_bind) { - // We'll be ignoring the 'this' pointer, but we need to make sure we pass - // a valid value to bindmemfunc(). - bindmemfunc(pParent, static_function_invoker); + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } // WARNING! Evil hack. We store the function in the 'this' pointer! // Ensure that there's a compilation failure if function pointers @@ -780,6 +801,13 @@ public: } #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } }; @@ -816,6 +844,14 @@ public: // it cannot be void. DesiredRetType is the real type which is returned from // all of the functions. It can be void. +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + //N=0 template class FastDelegate0 { @@ -824,7 +860,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(); typedef RetType (*UnvoidStaticFunctionPtr)(); typedef RetType (detail::GenericClass::*GenericMemFn)(); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate0 type; @@ -858,15 +895,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate0(DesiredRetType (*function_to_bind)() ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)()) { m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, function_to_bind); } - RetType operator() () const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() () const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -889,7 +945,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate1 type; @@ -923,15 +980,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) { m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -954,7 +1030,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate2 type; @@ -988,15 +1065,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) { m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1019,7 +1115,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate3 type; @@ -1053,15 +1150,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1084,7 +1200,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate4 type; @@ -1118,15 +1235,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1149,7 +1285,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate5 type; @@ -1183,15 +1320,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1214,7 +1370,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate6 type; @@ -1248,15 +1405,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1279,7 +1455,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate7 type; @@ -1313,15 +1490,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1344,7 +1540,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate8 type; @@ -1378,15 +1575,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1409,7 +1625,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate9 type; @@ -1443,15 +1660,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate9(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { m_Closure.bindstaticfunc(this, &FastDelegate9::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1474,7 +1710,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate10 type; @@ -1508,15 +1745,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate10(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { m_Closure.bindstaticfunc(this, &FastDelegate10::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1539,7 +1795,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate11 type; @@ -1573,15 +1830,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1604,7 +1880,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate12 type; @@ -1638,15 +1915,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1669,7 +1965,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate13 type; @@ -1703,15 +2000,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1734,7 +2050,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate14 type; @@ -1768,15 +2085,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate14(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { m_Closure.bindstaticfunc(this, &FastDelegate14::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1799,7 +2135,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate15 type; @@ -1833,15 +2170,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate15(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { m_Closure.bindstaticfunc(this, &FastDelegate15::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1864,7 +2220,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate16 type; @@ -1898,15 +2255,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate16(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { m_Closure.bindstaticfunc(this, &FastDelegate16::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1929,7 +2305,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate17 type; @@ -1963,15 +2340,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate17(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { m_Closure.bindstaticfunc(this, &FastDelegate17::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1994,7 +2390,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate18 type; @@ -2028,15 +2425,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate18(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { m_Closure.bindstaticfunc(this, &FastDelegate18::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -2059,7 +2475,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate19 type; @@ -2093,15 +2510,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate19(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { m_Closure.bindstaticfunc(this, &FastDelegate19::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -2124,7 +2560,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate20 type; @@ -2158,15 +2595,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate20(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { m_Closure.bindstaticfunc(this, &FastDelegate20::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -2207,8 +2663,7 @@ class FastDelegate; // FastDelegate0 < R > template class FastDelegate< R ( ) > - // Inherit from FastDelegate0 so that it can be treated just - // like a FastDelegate0 + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 : public FastDelegate0 < R > { public: @@ -2245,8 +2700,7 @@ public: // FastDelegate1 < Param1, R > template class FastDelegate< R ( Param1 ) > - // Inherit from FastDelegate1 so that it can be treated just - // like a FastDelegate1 + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 : public FastDelegate1 < Param1, R > { public: @@ -2283,8 +2737,7 @@ public: // FastDelegate2 < Param1, Param2, R > template class FastDelegate< R ( Param1, Param2 ) > - // Inherit from FastDelegate2 so that it can be treated just - // like a FastDelegate2 + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 : public FastDelegate2 < Param1, Param2, R > { public: @@ -2321,8 +2774,7 @@ public: // FastDelegate3 < Param1, Param2, Param3, R > template class FastDelegate< R ( Param1, Param2, Param3 ) > - // Inherit from FastDelegate3 so that it can be treated just - // like a FastDelegate3 + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 : public FastDelegate3 < Param1, Param2, Param3, R > { public: @@ -2359,8 +2811,7 @@ public: // FastDelegate4 < Param1, Param2, Param3, Param4, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4 ) > - // Inherit from FastDelegate4 so that it can be treated just - // like a FastDelegate4 + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 : public FastDelegate4 < Param1, Param2, Param3, Param4, R > { public: @@ -2397,8 +2848,7 @@ public: // FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > - // Inherit from FastDelegate5 so that it can be treated just - // like a FastDelegate5 + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > { public: @@ -2435,8 +2885,7 @@ public: // FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > - // Inherit from FastDelegate6 so that it can be treated just - // like a FastDelegate6 + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > { public: @@ -2473,8 +2922,7 @@ public: // FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > - // Inherit from FastDelegate7 so that it can be treated just - // like a FastDelegate7 + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > { public: @@ -2511,8 +2959,7 @@ public: // FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > - // Inherit from FastDelegate8 so that it can be treated just - // like a FastDelegate8 + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > { public: @@ -2549,8 +2996,7 @@ public: // FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > - // Inherit from FastDelegate9 so that it can be treated just - // like a FastDelegate9 + // Inherit from FastDelegate9 so that it can be treated just like a FastDelegate9 : public FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > { public: @@ -2587,8 +3033,7 @@ public: // FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > - // Inherit from FastDelegate10 so that it can be treated just - // like a FastDelegate10 + // Inherit from FastDelegate10 so that it can be treated just like a FastDelegate10 : public FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > { public: @@ -2625,8 +3070,7 @@ public: // FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > - // Inherit from FastDelegate11 so that it can be treated just - // like a FastDelegate11 + // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11 : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > { public: @@ -2663,8 +3107,7 @@ public: // FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > - // Inherit from FastDelegate12 so that it can be treated just - // like a FastDelegate12 + // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12 : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > { public: @@ -2701,8 +3144,7 @@ public: // FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > - // Inherit from FastDelegate13 so that it can be treated just - // like a FastDelegate13 + // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13 : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > { public: @@ -2739,8 +3181,7 @@ public: // FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > - // Inherit from FastDelegate14 so that it can be treated just - // like a FastDelegate14 + // Inherit from FastDelegate14 so that it can be treated just like a FastDelegate14 : public FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > { public: @@ -2777,8 +3218,7 @@ public: // FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > - // Inherit from FastDelegate15 so that it can be treated just - // like a FastDelegate15 + // Inherit from FastDelegate15 so that it can be treated just like a FastDelegate15 : public FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > { public: @@ -2815,8 +3255,7 @@ public: // FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > - // Inherit from FastDelegate16 so that it can be treated just - // like a FastDelegate16 + // Inherit from FastDelegate16 so that it can be treated just like a FastDelegate16 : public FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > { public: @@ -2853,8 +3292,7 @@ public: // FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > - // Inherit from FastDelegate17 so that it can be treated just - // like a FastDelegate17 + // Inherit from FastDelegate17 so that it can be treated just like a FastDelegate17 : public FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > { public: @@ -2891,8 +3329,7 @@ public: // FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > - // Inherit from FastDelegate18 so that it can be treated just - // like a FastDelegate18 + // Inherit from FastDelegate18 so that it can be treated just like a FastDelegate18 : public FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > { public: @@ -2929,8 +3366,7 @@ public: // FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > - // Inherit from FastDelegate19 so that it can be treated just - // like a FastDelegate19 + // Inherit from FastDelegate19 so that it can be treated just like a FastDelegate19 : public FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > { public: @@ -2967,8 +3403,7 @@ public: // FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > - // Inherit from FastDelegate20 so that it can be treated just - // like a FastDelegate20 + // Inherit from FastDelegate20 so that it can be treated just like a FastDelegate20 : public FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > { public: diff --git a/sourcehook/generate/FastDelegate.h b/sourcehook/generate/FastDelegate.h index 1b45fe0..5a02808 100644 --- a/sourcehook/generate/FastDelegate.h +++ b/sourcehook/generate/FastDelegate.h @@ -5,7 +5,7 @@ // - Don Clugston, Mar 2004. // Major contributions were made by Jody Hagins. // History: -// 24-Apr-04 1.0 Submitted to CodeProject. +// 24-Apr-04 1.0 * Submitted to CodeProject. // 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. // * Improved syntax for horrible_cast (thanks Paul Bludov). // * Tested on Metrowerks MWCC and Intel ICL (IA32) @@ -30,14 +30,20 @@ // * Less use of macros. Error messages should be more comprehensible. // * Added include guards // * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). -// * Now tested on VS 2005 Beta, PGI C++ +// * Now tested on VS 2005 Express Beta, PGI C++ // 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. // * <,>,<=,>= comparison operators to allow storage in ordered containers. // * Substantial reduction of code size, especially the 'Closure' class. // * Standardised all the compiler-specific workarounds. // * MFP conversion now works for CodePlay (but not yet supported in the full code). -// * Now compiles without warnings on _any_ compiler, including BCC 5.5.1 +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 // * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. #ifndef FASTDELEGATE_H #define FASTDELEGATE_H @@ -531,8 +537,10 @@ struct SimplifyMemFunc // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ // | 0 | 0 | 0 | Empty | // | !=0 |(dontcare)| Invoker | Static function| -// | 0 | !=0 | !=0 | Method call | +// | 0 | !=0 | !=0* | Method call | // +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). // When stored stored inside a specific delegate, the 'dontcare' entries are replaced // with a reference to the delegate itself. This complicates the = and == operators // for the delegate class. @@ -544,9 +552,11 @@ struct SimplifyMemFunc // horrible_cast. In this case the DelegateMemento implementation is simple: // +--pThis --+-- pMemFunc-+-- Meaning---------------------+ // | 0 | 0 | Empty | -// | !=0 | !=0 | Static function or method call| +// | !=0 | !=0* | Static function or method call| // +----------+------------+-------------------------------+ -// Note that the Sun C++ and MSVC documentation explicitly state that they +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they // support static_cast between void * and function pointers. class DelegateMemento { @@ -570,9 +580,7 @@ public: } #else DelegateMemento() : m_pthis(0), m_pFunction(0) {}; - void clear() { - m_pthis=0; m_pFunction=0; - } + void clear() { m_pthis=0; m_pFunction=0; } #endif public: #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) @@ -603,8 +611,13 @@ public: return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! inline bool operator ! () const // Is it bound to anything? - { return m_pFunction==0; } + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } public: DelegateMemento & operator = (const DelegateMemento &right) { SetMementoFrom(right); @@ -723,7 +736,11 @@ public: template < class DerivedClass, class ParentInvokerSig > inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, StaticFuncPtr function_to_bind ) { - bindmemfunc(pParent, static_function_invoker); + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } m_pStaticFunction=reinterpret_cast(function_to_bind); } inline UnvoidStaticFuncPtr GetStaticFunction() const { @@ -752,9 +769,13 @@ public: template < class DerivedClass, class ParentInvokerSig> inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, StaticFuncPtr function_to_bind) { - // We'll be ignoring the 'this' pointer, but we need to make sure we pass - // a valid value to bindmemfunc(). - bindmemfunc(pParent, static_function_invoker); + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } // WARNING! Evil hack. We store the function in the 'this' pointer! // Ensure that there's a compilation failure if function pointers @@ -780,6 +801,13 @@ public: } #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } }; @@ -816,6 +844,14 @@ public: // it cannot be void. DesiredRetType is the real type which is returned from // all of the functions. It can be void. +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + //N=0 template class FastDelegate0 { @@ -824,7 +860,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(); typedef RetType (*UnvoidStaticFunctionPtr)(); typedef RetType (detail::GenericClass::*GenericMemFn)(); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate0 type; @@ -858,15 +895,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate0(DesiredRetType (*function_to_bind)() ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)()) { m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, function_to_bind); } - RetType operator() () const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() () const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -889,7 +945,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate1 type; @@ -923,15 +980,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) { m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -954,7 +1030,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate2 type; @@ -988,15 +1065,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) { m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1019,7 +1115,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate3 type; @@ -1053,15 +1150,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1084,7 +1200,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate4 type; @@ -1118,15 +1235,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1149,7 +1285,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate5 type; @@ -1183,15 +1320,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1214,7 +1370,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate6 type; @@ -1248,15 +1405,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1279,7 +1455,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate7 type; @@ -1313,15 +1490,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1344,7 +1540,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate8 type; @@ -1378,15 +1575,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1409,7 +1625,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate9 type; @@ -1443,15 +1660,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate9(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { m_Closure.bindstaticfunc(this, &FastDelegate9::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1474,7 +1710,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate10 type; @@ -1508,15 +1745,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate10(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { m_Closure.bindstaticfunc(this, &FastDelegate10::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1539,7 +1795,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate11 type; @@ -1573,15 +1830,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1604,7 +1880,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate12 type; @@ -1638,15 +1915,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1669,7 +1965,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate13 type; @@ -1703,15 +2000,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1734,7 +2050,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate14 type; @@ -1768,15 +2085,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate14(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { m_Closure.bindstaticfunc(this, &FastDelegate14::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1799,7 +2135,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate15 type; @@ -1833,15 +2170,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate15(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { m_Closure.bindstaticfunc(this, &FastDelegate15::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1864,7 +2220,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate16 type; @@ -1898,15 +2255,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate16(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { m_Closure.bindstaticfunc(this, &FastDelegate16::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1929,7 +2305,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate17 type; @@ -1963,15 +2340,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate17(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { m_Closure.bindstaticfunc(this, &FastDelegate17::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -1994,7 +2390,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate18 type; @@ -2028,15 +2425,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate18(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { m_Closure.bindstaticfunc(this, &FastDelegate18::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -2059,7 +2475,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate19 type; @@ -2093,15 +2510,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate19(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { m_Closure.bindstaticfunc(this, &FastDelegate19::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -2124,7 +2560,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate20 type; @@ -2158,15 +2595,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate20(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { m_Closure.bindstaticfunc(this, &FastDelegate20::InvokeStaticFunction, function_to_bind); } - RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -2207,8 +2663,7 @@ class FastDelegate; // FastDelegate0 < R > template class FastDelegate< R ( ) > - // Inherit from FastDelegate0 so that it can be treated just - // like a FastDelegate0 + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 : public FastDelegate0 < R > { public: @@ -2245,8 +2700,7 @@ public: // FastDelegate1 < Param1, R > template class FastDelegate< R ( Param1 ) > - // Inherit from FastDelegate1 so that it can be treated just - // like a FastDelegate1 + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 : public FastDelegate1 < Param1, R > { public: @@ -2283,8 +2737,7 @@ public: // FastDelegate2 < Param1, Param2, R > template class FastDelegate< R ( Param1, Param2 ) > - // Inherit from FastDelegate2 so that it can be treated just - // like a FastDelegate2 + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 : public FastDelegate2 < Param1, Param2, R > { public: @@ -2321,8 +2774,7 @@ public: // FastDelegate3 < Param1, Param2, Param3, R > template class FastDelegate< R ( Param1, Param2, Param3 ) > - // Inherit from FastDelegate3 so that it can be treated just - // like a FastDelegate3 + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 : public FastDelegate3 < Param1, Param2, Param3, R > { public: @@ -2359,8 +2811,7 @@ public: // FastDelegate4 < Param1, Param2, Param3, Param4, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4 ) > - // Inherit from FastDelegate4 so that it can be treated just - // like a FastDelegate4 + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 : public FastDelegate4 < Param1, Param2, Param3, Param4, R > { public: @@ -2397,8 +2848,7 @@ public: // FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > - // Inherit from FastDelegate5 so that it can be treated just - // like a FastDelegate5 + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > { public: @@ -2435,8 +2885,7 @@ public: // FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > - // Inherit from FastDelegate6 so that it can be treated just - // like a FastDelegate6 + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > { public: @@ -2473,8 +2922,7 @@ public: // FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > - // Inherit from FastDelegate7 so that it can be treated just - // like a FastDelegate7 + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > { public: @@ -2511,8 +2959,7 @@ public: // FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > - // Inherit from FastDelegate8 so that it can be treated just - // like a FastDelegate8 + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > { public: @@ -2549,8 +2996,7 @@ public: // FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > - // Inherit from FastDelegate9 so that it can be treated just - // like a FastDelegate9 + // Inherit from FastDelegate9 so that it can be treated just like a FastDelegate9 : public FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > { public: @@ -2587,8 +3033,7 @@ public: // FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > - // Inherit from FastDelegate10 so that it can be treated just - // like a FastDelegate10 + // Inherit from FastDelegate10 so that it can be treated just like a FastDelegate10 : public FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > { public: @@ -2625,8 +3070,7 @@ public: // FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > - // Inherit from FastDelegate11 so that it can be treated just - // like a FastDelegate11 + // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11 : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > { public: @@ -2663,8 +3107,7 @@ public: // FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > - // Inherit from FastDelegate12 so that it can be treated just - // like a FastDelegate12 + // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12 : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > { public: @@ -2701,8 +3144,7 @@ public: // FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > - // Inherit from FastDelegate13 so that it can be treated just - // like a FastDelegate13 + // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13 : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > { public: @@ -2739,8 +3181,7 @@ public: // FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > - // Inherit from FastDelegate14 so that it can be treated just - // like a FastDelegate14 + // Inherit from FastDelegate14 so that it can be treated just like a FastDelegate14 : public FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > { public: @@ -2777,8 +3218,7 @@ public: // FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > - // Inherit from FastDelegate15 so that it can be treated just - // like a FastDelegate15 + // Inherit from FastDelegate15 so that it can be treated just like a FastDelegate15 : public FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > { public: @@ -2815,8 +3255,7 @@ public: // FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > - // Inherit from FastDelegate16 so that it can be treated just - // like a FastDelegate16 + // Inherit from FastDelegate16 so that it can be treated just like a FastDelegate16 : public FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > { public: @@ -2853,8 +3292,7 @@ public: // FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > - // Inherit from FastDelegate17 so that it can be treated just - // like a FastDelegate17 + // Inherit from FastDelegate17 so that it can be treated just like a FastDelegate17 : public FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > { public: @@ -2891,8 +3329,7 @@ public: // FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > - // Inherit from FastDelegate18 so that it can be treated just - // like a FastDelegate18 + // Inherit from FastDelegate18 so that it can be treated just like a FastDelegate18 : public FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > { public: @@ -2929,8 +3366,7 @@ public: // FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > - // Inherit from FastDelegate19 so that it can be treated just - // like a FastDelegate19 + // Inherit from FastDelegate19 so that it can be treated just like a FastDelegate19 : public FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > { public: @@ -2967,8 +3403,7 @@ public: // FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > template class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > - // Inherit from FastDelegate20 so that it can be treated just - // like a FastDelegate20 + // Inherit from FastDelegate20 so that it can be treated just like a FastDelegate20 : public FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > { public: diff --git a/sourcehook/generate/FastDelegate.hxx b/sourcehook/generate/FastDelegate.hxx index ba45d4d..6a5de88 100644 --- a/sourcehook/generate/FastDelegate.hxx +++ b/sourcehook/generate/FastDelegate.hxx @@ -5,7 +5,7 @@ // - Don Clugston, Mar 2004. // Major contributions were made by Jody Hagins. // History: -// 24-Apr-04 1.0 Submitted to CodeProject. +// 24-Apr-04 1.0 * Submitted to CodeProject. // 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. // * Improved syntax for horrible_cast (thanks Paul Bludov). // * Tested on Metrowerks MWCC and Intel ICL (IA32) @@ -30,14 +30,20 @@ // * Less use of macros. Error messages should be more comprehensible. // * Added include guards // * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). -// * Now tested on VS 2005 Beta, PGI C++ +// * Now tested on VS 2005 Express Beta, PGI C++ // 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. // * <,>,<=,>= comparison operators to allow storage in ordered containers. // * Substantial reduction of code size, especially the 'Closure' class. // * Standardised all the compiler-specific workarounds. // * MFP conversion now works for CodePlay (but not yet supported in the full code). -// * Now compiles without warnings on _any_ compiler, including BCC 5.5.1 +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 // * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. #ifndef FASTDELEGATE_H #define FASTDELEGATE_H @@ -531,8 +537,10 @@ struct SimplifyMemFunc // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ // | 0 | 0 | 0 | Empty | // | !=0 |(dontcare)| Invoker | Static function| -// | 0 | !=0 | !=0 | Method call | +// | 0 | !=0 | !=0* | Method call | // +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). // When stored stored inside a specific delegate, the 'dontcare' entries are replaced // with a reference to the delegate itself. This complicates the = and == operators // for the delegate class. @@ -544,9 +552,11 @@ struct SimplifyMemFunc // horrible_cast. In this case the DelegateMemento implementation is simple: // +--pThis --+-- pMemFunc-+-- Meaning---------------------+ // | 0 | 0 | Empty | -// | !=0 | !=0 | Static function or method call| +// | !=0 | !=0* | Static function or method call| // +----------+------------+-------------------------------+ -// Note that the Sun C++ and MSVC documentation explicitly state that they +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they // support static_cast between void * and function pointers. class DelegateMemento { @@ -570,9 +580,7 @@ public: } #else DelegateMemento() : m_pthis(0), m_pFunction(0) {}; - void clear() { - m_pthis=0; m_pFunction=0; - } + void clear() { m_pthis=0; m_pFunction=0; } #endif public: #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) @@ -603,8 +611,13 @@ public: return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! inline bool operator ! () const // Is it bound to anything? - { return m_pFunction==0; } + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } public: DelegateMemento & operator = (const DelegateMemento &right) { SetMementoFrom(right); @@ -723,7 +736,11 @@ public: template < class DerivedClass, class ParentInvokerSig > inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, StaticFuncPtr function_to_bind ) { - bindmemfunc(pParent, static_function_invoker); + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } m_pStaticFunction=reinterpret_cast(function_to_bind); } inline UnvoidStaticFuncPtr GetStaticFunction() const { @@ -752,9 +769,13 @@ public: template < class DerivedClass, class ParentInvokerSig> inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, StaticFuncPtr function_to_bind) { - // We'll be ignoring the 'this' pointer, but we need to make sure we pass - // a valid value to bindmemfunc(). - bindmemfunc(pParent, static_function_invoker); + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } // WARNING! Evil hack. We store the function in the 'this' pointer! // Ensure that there's a compilation failure if function pointers @@ -780,6 +801,13 @@ public: } #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } }; @@ -816,6 +844,14 @@ public: // it cannot be void. DesiredRetType is the real type which is returned from // all of the functions. It can be void. +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + @VARARGS template<@CLASSARGS, class RetType=detail::DefaultVoid> class FastDelegate@NUM { @@ -824,7 +860,8 @@ private: typedef DesiredRetType (*StaticFunctionPtr)(@FUNCARGS); typedef RetType (*UnvoidStaticFunctionPtr)(@FUNCARGS); typedef RetType (detail::GenericClass::*GenericMemFn)(@FUNCARGS); - detail::ClosurePtr m_Closure; + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: // Typedefs to aid generic programming typedef FastDelegate@NUM type; @@ -858,15 +895,34 @@ public: inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) const) { m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. - // Note that this also provides a conversion from static functions. + // This constructor also provides implicit conversion FastDelegate@NUM(DesiredRetType (*function_to_bind)(@FUNCARGS) ) { bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(@FUNCARGS) ) { + bind(function_to_bind); } inline void bind(DesiredRetType (*function_to_bind)(@FUNCARGS)) { m_Closure.bindstaticfunc(this, &FastDelegate@NUM::InvokeStaticFunction, function_to_bind); } - RetType operator() (@FUNCARGS) const { // Invoke the delegate - // this next line is the only one that violates the standard + // Invoke the delegate + RetType operator() (@FUNCARGS) const { return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(@INVOKEARGS); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? return !m_Closure; } inline bool empty() const { @@ -908,8 +964,7 @@ class FastDelegate; // FastDelegate@NUM < @SELARGS, R > template class FastDelegate< R ( @SELARGS ) > - // Inherit from FastDelegate@NUM so that it can be treated just - // like a FastDelegate@NUM + // Inherit from FastDelegate@NUM so that it can be treated just like a FastDelegate@NUM : public FastDelegate@NUM < @SELARGS, R > { public: diff --git a/sourcehook/test/testreentr.cpp b/sourcehook/test/testreentr.cpp index 94b6bb3..5a85658 100644 --- a/sourcehook/test/testreentr.cpp +++ b/sourcehook/test/testreentr.cpp @@ -66,6 +66,10 @@ namespace MAKE_STATE_1(State_H_C7_G, C7*); MAKE_STATE_1(State_H_C8_G, C8*); + MAKE_STATE_1(State_H2_C4_G, C4*); + + int g_TestID; + struct C1 { virtual void F() @@ -163,6 +167,23 @@ namespace } }; + SH_DECL_HOOK0_void(C1, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C1, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C2, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C2, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C3, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C3, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C4, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C4, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C5, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C5, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C6, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C6, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C7, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C7, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C8, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C8, G, SH_NOATTRIB, 0, int); + void Handler_C1_F() { ADD_STATE(State_H_C1_F(META_IFACEPTR(C1))); @@ -207,6 +228,11 @@ namespace g_pC5->F(); return 4; } + int Handler2_C4_G() + { + ADD_STATE(State_H2_C4_G(META_IFACEPTR(C4))); + return 4; + } void Handler_C5_F() { ADD_STATE(State_H_C5_F(META_IFACEPTR(C5))); @@ -231,6 +257,11 @@ namespace } void Handler_C7_F() { + if (g_TestID == 1 || g_TestID == 2) + SH_REMOVE_HOOK_STATICFUNC(C4, G, g_pC4, Handler2_C4_G, false); + if (g_TestID == 2) + SH_REMOVE_HOOK_STATICFUNC(C4, G, g_pC4, Handler_C4_G, false); + ADD_STATE(State_H_C7_F(META_IFACEPTR(C7))); g_pC7->G(); } @@ -259,23 +290,6 @@ namespace C6 g_C6; C7 g_C7; C8 g_C8; - - SH_DECL_HOOK0_void(C1, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C1, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C2, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C2, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C3, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C3, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C4, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C4, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C5, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C5, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C6, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C6, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C7, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C7, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C8, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C8, G, SH_NOATTRIB, 0, int); } bool TestReentr(std::string &error) @@ -347,5 +361,223 @@ bool TestReentr(std::string &error) new State_C1_F(g_pC1), NULL), "1"); + + SH_ADD_HOOK_STATICFUNC(C4, G, g_pC4, Handler2_C4_G, false); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_H2_C4_G(g_pC4), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "2"); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_H2_C4_G(g_pC4), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "3"); + + g_TestID = 1; + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "4"); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "5"); + + + + SH_ADD_HOOK_STATICFUNC(C4, G, g_pC4, Handler2_C4_G, false); + + g_TestID = 2; + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "6"); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "7"); + return true; } \ No newline at end of file