Shadowrun: Awakened 29 September 2011 - Build 871
FastDelegate.h
Go to the documentation of this file.
00001 //                        FastDelegate.h 
00002 //    Efficient delegates in C++ that generate only two lines of asm code!
00003 //  Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
00004 //
00005 //                        - Don Clugston, Mar 2004.
00006 //        Major contributions were made by Jody Hagins.
00007 // History:
00008 // 24-Apr-04 1.0  * Submitted to CodeProject. 
00009 // 28-Apr-04 1.1  * Prevent most unsafe uses of evil static function hack.
00010 //                  * Improved syntax for horrible_cast (thanks Paul Bludov).
00011 //                  * Tested on Metrowerks MWCC and Intel ICL (IA32)
00012 //                  * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
00013 //    27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
00014 //                  * Now works on /clr "managed C++" code on VC7, VC7.1
00015 //                  * Comeau C++ now compiles without warnings.
00016 //                  * Prevent the virtual inheritance case from being used on 
00017 //                      VC6 and earlier, which generate incorrect code.
00018 //                  * Improved warning and error messages. Non-standard hacks
00019 //                     now have compile-time checks to make them safer.
00020 //                  * implicit_cast used instead of static_cast in many cases.
00021 //                  * If calling a const member function, a const class pointer can be used.
00022 //                  * MakeDelegate() global helper function added to simplify pass-by-value.
00023 //                  * Added fastdelegate.clear()
00024 // 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)
00025 // 30-Oct-04 1.3  * Support for (non-void) return values.
00026 //                  * No more workarounds in client code!
00027 //                     MSVC and Intel now use a clever hack invented by John Dlugosz:
00028 //                     - The FASTDELEGATEDECLARE workaround is no longer necessary.
00029 //                     - No more warning messages for VC6
00030 //                  * Less use of macros. Error messages should be more comprehensible.
00031 //                  * Added include guards
00032 //                  * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks).
00033 //                  * Now tested on VS 2005 Express Beta, PGI C++
00034 // 24-Dec-04 1.4  * Added DelegateMemento, to allow collections of disparate delegates.
00035 //                * <,>,<=,>= comparison operators to allow storage in ordered containers.
00036 //                  * Substantial reduction of code size, especially the 'Closure' class.
00037 //                  * Standardised all the compiler-specific workarounds.
00038 //                * MFP conversion now works for CodePlay (but not yet supported in the full code).
00039 //                * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
00040 //                  * New syntax: FastDelegate< int (char *, double) >. 
00041 // 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric).
00042 //                  * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.
00043 // 30-Mar-05 1.5  * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())"
00044 //                  * Fully supported by CodePlay VectorC
00045 //                * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC!
00046 //                * More optimal assignment,== and != operators for static function pointers.
00047 
00048 #ifndef FASTDELEGATE_H
00049 #define FASTDELEGATE_H
00050 #if _MSC_VER > 1000
00051 #pragma once
00052 #endif // _MSC_VER > 1000
00053 
00054 #include <memory.h> // to allow <,> comparisons
00055 
00057 //                        Configuration options
00058 //
00060 
00061 // Uncomment the following #define for optimally-sized delegates.
00062 // In this case, the generated asm code is almost identical to the code you'd get
00063 // if the compiler had native support for delegates.
00064 // It will not work on systems where sizeof(dataptr) < sizeof(codeptr). 
00065 // Thus, it will not work for DOS compilers using the medium model.
00066 // It will also probably fail on some DSP systems.
00067 #define FASTDELEGATE_USESTATICFUNCTIONHACK
00068 
00069 // Uncomment the next line to allow function declarator syntax.
00070 // It is automatically enabled for those compilers where it is known to work.
00071 //#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00072 
00074 //                        Compiler identification for workarounds
00075 //
00077 
00078 // Compiler identification. It's not easy to identify Visual C++ because
00079 // many vendors fraudulently define Microsoft's identifiers.
00080 #if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)
00081 #define FASTDLGT_ISMSVC
00082 
00083 #if (_MSC_VER <1300) // Many workarounds are required for VC6.
00084 #define FASTDLGT_VC6
00085 #pragma warning(disable:4786) // disable this ridiculous warning
00086 #endif
00087 
00088 #endif
00089 
00090 // Does the compiler uses Microsoft's member function pointer structure?
00091 // If so, it needs special treatment.
00092 // Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's 
00093 // identifier, _MSC_VER. We need to filter Metrowerks out.
00094 #if defined(_MSC_VER) && !defined(__MWERKS__)
00095 #define FASTDLGT_MICROSOFT_MFP
00096 
00097 #if !defined(__VECTOR_C)
00098 // CodePlay doesn't have the __single/multi/virtual_inheritance keywords
00099 #define FASTDLGT_HASINHERITANCE_KEYWORDS
00100 #endif
00101 #endif
00102 
00103 // Does it allow function declarator syntax? The following compilers are known to work:
00104 #if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1
00105 #define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00106 #endif
00107 
00108 // Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.
00109 #if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)
00110 #define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00111 #endif
00112 
00113 // It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
00114 #if defined (__MWERKS__)
00115 #define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00116 #endif
00117 
00118 #ifdef __GNUC__ // Workaround GCC bug #8271 
00119     // At present, GCC doesn't recognize constness of MFPs in templates
00120 #define FASTDELEGATE_GCC_BUG_8271
00121 #endif
00122 
00123 
00124 
00126 //                        General tricks used in this code
00127 //
00128 // (a) Error messages are generated by typdefing an array of negative size to
00129 //     generate compile-time errors.
00130 // (b) Warning messages on MSVC are generated by declaring unused variables, and
00131 //        enabling the "variable XXX is never used" warning.
00132 // (c) Unions are used in a few compiler-specific cases to perform illegal casts.
00133 // (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
00134 //     (char *) first to ensure that the correct number of *bytes* are added.
00135 //
00137 //                        Helper templates
00138 //
00140 
00141 
00142 namespace fastdelegate {
00143 namespace detail {    // we'll hide the implementation details in a nested namespace.
00144 
00145 //        implicit_cast< >
00146 // I believe this was originally going to be in the C++ standard but 
00147 // was left out by accident. It's even milder than static_cast.
00148 // I use it instead of static_cast<> to emphasize that I'm not doing
00149 // anything nasty. 
00150 // Usage is identical to static_cast<>
00151 template <class OutputClass, class InputClass>
00152 inline OutputClass implicit_cast(InputClass input){
00153     return input;
00154 }
00155 
00156 //        horrible_cast< >
00157 // This is truly evil. It completely subverts C++'s type system, allowing you 
00158 // to cast from any class to any other class. Technically, using a union 
00159 // to perform the cast is undefined behaviour (even in C). But we can see if
00160 // it is OK by checking that the union is the same size as each of its members.
00161 // horrible_cast<> should only be used for compiler-specific workarounds. 
00162 // Usage is identical to reinterpret_cast<>.
00163 
00164 // This union is declared outside the horrible_cast because BCC 5.5.1
00165 // can't inline a function with a nested class, and gives a warning.
00166 template <class OutputClass, class InputClass>
00167 union horrible_union{
00168     OutputClass out;
00169     InputClass in;
00170 };
00171 
00172 template <class OutputClass, class InputClass>
00173 inline OutputClass horrible_cast(const InputClass input){
00174     horrible_union<OutputClass, InputClass> u;
00175     // Cause a compile-time error if in, out and u are not the same size.
00176     // If the compile fails here, it means the compiler has peculiar
00177     // unions which would prevent the cast from working.
00178     typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) 
00179         && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
00180     u.in = input;
00181     return u.out;
00182 }
00183 
00185 //                        Workarounds
00186 //
00188 
00189 // Backwards compatibility: This macro used to be necessary in the virtual inheritance
00190 // case for Intel and Microsoft. Now it just forward-declares the class.
00191 #define FASTDELEGATEDECLARE(CLASSNAME)    class CLASSNAME;
00192 
00193 // Prevent use of the static function hack with the DOS medium model.
00194 #ifdef __MEDIUM__
00195 #undef FASTDELEGATE_USESTATICFUNCTIONHACK
00196 #endif
00197 
00198 //            DefaultVoid - a workaround for 'void' templates in VC6.
00199 //
00200 //  (1) VC6 and earlier do not allow 'void' as a default template argument.
00201 //  (2) They also doesn't allow you to return 'void' from a function.
00202 //
00203 // Workaround for (1): Declare a dummy type 'DefaultVoid' which we use
00204 //   when we'd like to use 'void'. We convert it into 'void' and back
00205 //   using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
00206 // Workaround for (2): On VC6, the code for calling a void function is
00207 //   identical to the code for calling a non-void function in which the
00208 //   return value is never used, provided the return value is returned
00209 //   in the EAX register, rather than on the stack. 
00210 //   This is true for most fundamental types such as int, enum, void *.
00211 //   Const void * is the safest option since it doesn't participate 
00212 //   in any automatic conversions. But on a 16-bit compiler it might
00213 //   cause extra code to be generated, so we disable it for all compilers
00214 //   except for VC6 (and VC5).
00215 #ifdef FASTDLGT_VC6
00216 // VC6 workaround
00217 typedef const void * DefaultVoid;
00218 #else
00219 // On any other compiler, just use a normal void.
00220 typedef void DefaultVoid;
00221 #endif
00222 
00223 // Translate from 'DefaultVoid' to 'void'.
00224 // Everything else is unchanged
00225 template <class T>
00226 struct DefaultVoidToVoid { typedef T type; };
00227 
00228 template <>
00229 struct DefaultVoidToVoid<DefaultVoid> {    typedef void type; };
00230 
00231 // Translate from 'void' into 'DefaultVoid'
00232 // Everything else is unchanged
00233 template <class T>
00234 struct VoidToDefaultVoid { typedef T type; };
00235 
00236 template <>
00237 struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
00238 
00239 
00240 
00242 //                        Fast Delegates, part 1:
00243 //
00244 //        Conversion of member function pointer to a standard form
00245 //
00247 
00248 // GenericClass is a fake class, ONLY used to provide a type.
00249 // It is vitally important that it is never defined, so that the compiler doesn't
00250 // think it can optimize the invocation. For example, Borland generates simpler
00251 // code if it knows the class only uses single inheritance.
00252 
00253 // Compilers using Microsoft's structure need to be treated as a special case.
00254 #ifdef  FASTDLGT_MICROSOFT_MFP
00255 
00256 #ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
00257     // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP 
00258     // (4 bytes), even when the /vmg option is used. Declaring an empty class 
00259     // would give 16 byte pointers in this case....
00260     class __single_inheritance GenericClass;
00261 #endif
00262     // ...but for Codeplay, an empty class *always* gives 4 byte pointers.
00263     // If compiled with the /clr option ("managed C++"), the JIT compiler thinks
00264     // it needs to load GenericClass before it can call any of its functions,
00265     // (compiles OK but crashes at runtime!), so we need to declare an 
00266     // empty class to make it happy.
00267     // Codeplay and VC4 can't cope with the unknown_inheritance case either.
00268     class GenericClass {};
00269 #else
00270     class GenericClass;
00271 #endif
00272 
00273 // The size of a single inheritance member function pointer.
00274 const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());
00275 
00276 //                        SimplifyMemFunc< >::Convert()
00277 //
00278 //    A template function that converts an arbitrary member function pointer into the 
00279 //    simplest possible form of member function pointer, using a supplied 'this' pointer.
00280 //  According to the standard, this can be done legally with reinterpret_cast<>.
00281 //    For (non-standard) compilers which use member function pointers which vary in size 
00282 //  depending on the class, we need to use    knowledge of the internal structure of a 
00283 //  member function pointer, as used by the compiler. Template specialization is used
00284 //  to distinguish between the sizes. Because some compilers don't support partial 
00285 //    template specialisation, I use full specialisation of a wrapper struct.
00286 
00287 // general case -- don't know how to convert it. Force a compile failure
00288 template <int N>
00289 struct SimplifyMemFunc {
00290     template <class X, class XFuncType, class GenericMemFuncType>
00291     inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00292         GenericMemFuncType &bound_func) { 
00293         // Unsupported member function type -- force a compile failure.
00294         // (it's illegal to have a array with negative size).
00295         typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
00296         return 0; 
00297     }
00298 };
00299 
00300 // For compilers where all member func ptrs are the same size, everything goes here.
00301 // For non-standard compilers, only single_inheritance classes go here.
00302 template <>
00303 struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE>  {    
00304     template <class X, class XFuncType, class GenericMemFuncType>
00305     inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00306             GenericMemFuncType &bound_func) {
00307 #if defined __DMC__  
00308         // Digital Mars doesn't allow you to cast between abitrary PMF's, 
00309         // even though the standard says you can. The 32-bit compiler lets you
00310         // static_cast through an int, but the DOS compiler doesn't.
00311         bound_func = horrible_cast<GenericMemFuncType>(function_to_bind);
00312 #else 
00313         bound_func = reinterpret_cast<GenericMemFuncType>(function_to_bind);
00314 #endif
00315         return reinterpret_cast<GenericClass *>(pthis);
00316     }
00317 };
00318 
00320 //                        Fast Delegates, part 1b:
00321 //
00322 //                    Workarounds for Microsoft and Intel
00323 //
00325 
00326 
00327 // Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
00328 // need to be treated as a special case.
00329 #ifdef FASTDLGT_MICROSOFT_MFP
00330 
00331 // We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
00332 // at the start of each function for extra safety, but VC6 seems to ICE
00333 // intermittently if you do this inside a template.
00334 
00335 // __multiple_inheritance classes go here
00336 // Nasty hack for Microsoft and Intel (IA32 and Itanium)
00337 template<>
00338 struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) >  {
00339     template <class X, class XFuncType, class GenericMemFuncType>
00340     inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00341         GenericMemFuncType &bound_func) { 
00342         // We need to use a horrible_cast to do this conversion.
00343         // In MSVC, a multiple inheritance member pointer is internally defined as:
00344         union {
00345             XFuncType func;
00346             struct {     
00347                 GenericMemFuncType funcaddress; // points to the actual member function
00348                 int delta;         // #BYTES to be added to the 'this' pointer
00349             }s;
00350         } u;
00351         // Check that the horrible_cast will work
00352         typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1];
00353         u.func = function_to_bind;
00354         bound_func = u.s.funcaddress;
00355         return reinterpret_cast<GenericClass *>(reinterpret_cast<char *>(pthis) + u.s.delta); 
00356     }
00357 };
00358 
00359 // virtual inheritance is a real nuisance. It's inefficient and complicated.
00360 // On MSVC and Intel, there isn't enough information in the pointer itself to
00361 // enable conversion to a closure pointer. Earlier versions of this code didn't
00362 // work for all cases, and generated a compile-time error instead.
00363 // But a very clever hack invented by John M. Dlugosz solves this problem.
00364 // My code is somewhat different to his: I have no asm code, and I make no 
00365 // assumptions about the calling convention that is used.
00366 
00367 // In VC++ and ICL, a virtual_inheritance member pointer 
00368 // is internally defined as:
00369 struct MicrosoftVirtualMFP {
00370     void (GenericClass::*codeptr)(); // points to the actual member function
00371     int delta;        // #bytes to be added to the 'this' pointer
00372     int vtable_index; // or 0 if no virtual inheritance
00373 };
00374 // The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
00375 // m_codeptr member is *always* called, regardless of the values of the other
00376 // members. (This is *not* true for other compilers, eg GCC, which obtain the
00377 // function address from the vtable if a virtual function is being called).
00378 // Dlugosz's trick is to make the codeptr point to a probe function which
00379 // returns the 'this' pointer that was used.
00380 
00381 // Define a generic class that uses virtual inheritance.
00382 // It has a trival member function that returns the value of the 'this' pointer.
00383 struct GenericVirtualClass : virtual public GenericClass
00384 {
00385     typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
00386     GenericVirtualClass * GetThis() { return this; }
00387 };
00388 
00389 // __virtual_inheritance classes go here
00390 template <>
00391 struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 2*sizeof(int) >
00392 {
00393 
00394     template <class X, class XFuncType, class GenericMemFuncType>
00395     inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00396         GenericMemFuncType &bound_func) {
00397         union {
00398             XFuncType func;
00399             GenericClass* (X::*ProbeFunc)();
00400             MicrosoftVirtualMFP s;
00401         } u;
00402         u.func = function_to_bind;
00403         bound_func = reinterpret_cast<GenericMemFuncType>(u.s.codeptr);
00404         union {
00405             GenericVirtualClass::ProbePtrType virtfunc;
00406             MicrosoftVirtualMFP s;
00407         } u2;
00408         // Check that the horrible_cast<>s will work
00409         typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)
00410             && sizeof(function_to_bind)==sizeof(u.ProbeFunc)
00411             && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
00412    // Unfortunately, taking the address of a MF prevents it from being inlined, so 
00413    // this next line can't be completely optimised away by the compiler.
00414         u2.virtfunc = &GenericVirtualClass::GetThis;
00415         u.s.codeptr = u2.s.codeptr;
00416         return (pthis->*u.ProbeFunc)();
00417     }
00418 };
00419 
00420 #if (_MSC_VER <1300)
00421 
00422 // Nasty hack for Microsoft Visual C++ 6.0
00423 // unknown_inheritance classes go here
00424 // There is a compiler bug in MSVC6 which generates incorrect code in this case!!
00425 template <>
00426 struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
00427 {
00428     template <class X, class XFuncType, class GenericMemFuncType>
00429     inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00430         GenericMemFuncType &bound_func) {
00431         // There is an apalling but obscure compiler bug in MSVC6 and earlier:
00432         // vtable_index and 'vtordisp' are always set to 0 in the 
00433         // unknown_inheritance case!
00434         // This means that an incorrect function could be called!!!
00435         // Compiling with the /vmg option leads to potentially incorrect code.
00436         // This is probably the reason that the IDE has a user interface for specifying
00437         // the /vmg option, but it is disabled -  you can only specify /vmg on 
00438         // the command line. In VC1.5 and earlier, the compiler would ICE if it ever
00439         // encountered this situation.
00440         // It is OK to use the /vmg option if /vmm or /vms is specified.
00441 
00442         // Fortunately, the wrong function is only called in very obscure cases.
00443         // It only occurs when a derived class overrides a virtual function declared 
00444         // in a virtual base class, and the member function 
00445         // points to the *Derived* version of that function. The problem can be
00446         // completely averted in 100% of cases by using the *Base class* for the 
00447         // member fpointer. Ie, if you use the base class as an interface, you'll
00448         // stay out of trouble.
00449         // Occasionally, you might want to point directly to a derived class function
00450         // that isn't an override of a base class. In this case, both vtable_index 
00451         // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
00452         // We can generate correct code in this case. To prevent an incorrect call from
00453         // ever being made, on MSVC6 we generate a warning, and call a function to 
00454         // make the program crash instantly. 
00455         typedef char ERROR_VC6CompilerBug[-100];
00456         return 0; 
00457     }
00458 };
00459 
00460 
00461 #else 
00462 
00463 // Nasty hack for Microsoft and Intel (IA32 and Itanium)
00464 // unknown_inheritance classes go here 
00465 // This is probably the ugliest bit of code I've ever written. Look at the casts!
00466 // There is a compiler bug in MSVC6 which prevents it from using this code.
00467 template <>
00468 struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
00469 {
00470     template <class X, class XFuncType, class GenericMemFuncType>
00471     inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00472             GenericMemFuncType &bound_func) {
00473         // The member function pointer is 16 bytes long. We can't use a normal cast, but
00474         // we can use a union to do the conversion.
00475         union {
00476             XFuncType func;
00477             // In VC++ and ICL, an unknown_inheritance member pointer 
00478             // is internally defined as:
00479             struct {
00480                 GenericMemFuncType m_funcaddress; // points to the actual member function
00481                 int delta;        // #bytes to be added to the 'this' pointer
00482                 int vtordisp;        // #bytes to add to 'this' to find the vtable
00483                 int vtable_index; // or 0 if no virtual inheritance
00484             } s;
00485         } u;
00486         // Check that the horrible_cast will work
00487         typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1];
00488         u.func = function_to_bind;
00489         bound_func = u.s.funcaddress;
00490         int virtual_delta = 0;
00491         if (u.s.vtable_index) { // Virtual inheritance is used
00492             // First, get to the vtable. 
00493             // It is 'vtordisp' bytes from the start of the class.
00494             const int * vtable = *reinterpret_cast<const int *const*>(
00495                 reinterpret_cast<const char *>(pthis) + u.s.vtordisp );
00496 
00497             // 'vtable_index' tells us where in the table we should be looking.
00498             virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>( 
00499                 reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
00500         }
00501         // The int at 'virtual_delta' gives us the amount to add to 'this'.
00502         // Finally we can add the three components together. Phew!
00503         return reinterpret_cast<GenericClass *>(
00504             reinterpret_cast<char *>(pthis) + u.s.delta + virtual_delta);
00505     };
00506 };
00507 #endif // MSVC 7 and greater
00508 
00509 #endif // MS/Intel hacks
00510 
00511 }  // namespace detail
00512 
00514 //                        Fast Delegates, part 2:
00515 //
00516 //    Define the delegate storage, and cope with static functions
00517 //
00519 
00520 // DelegateMemento -- an opaque structure which can hold an arbitary delegate.
00521 // It knows nothing about the calling convention or number of arguments used by
00522 // the function pointed to.
00523 // It supplies comparison operators so that it can be stored in STL collections.
00524 // It cannot be set to anything other than null, nor invoked directly: 
00525 //   it must be converted to a specific delegate.
00526 
00527 // Implementation:
00528 // There are two possible implementations: the Safe method and the Evil method.
00529 //                DelegateMemento - Safe version
00530 //
00531 // This implementation is standard-compliant, but a bit tricky.
00532 // A static function pointer is stored inside the class. 
00533 // Here are the valid values:
00534 // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
00535 // |   0                |  0       |   0        | Empty          |
00536 // |   !=0              |(dontcare)|  Invoker   | Static function|
00537 // |   0                |  !=0     |  !=0*      | Method call    |
00538 // +--------------------+----------+------------+----------------+
00539 //  * For Metrowerks, this can be 0. (first virtual function in a 
00540 //       single_inheritance class).
00541 // When stored stored inside a specific delegate, the 'dontcare' entries are replaced
00542 // with a reference to the delegate itself. This complicates the = and == operators
00543 // for the delegate class.
00544 
00545 //                DelegateMemento - Evil version
00546 //
00547 // For compilers where data pointers are at least as big as code pointers, it is 
00548 // possible to store the function pointer in the this pointer, using another 
00549 // horrible_cast. In this case the DelegateMemento implementation is simple:
00550 // +--pThis --+-- pMemFunc-+-- Meaning---------------------+
00551 // |    0     |  0         | Empty                         |
00552 // |  !=0     |  !=0*      | Static function or method call|
00553 // +----------+------------+-------------------------------+
00554 //  * For Metrowerks, this can be 0. (first virtual function in a 
00555 //       single_inheritance class).
00556 // Note that the Sun C++ and MSVC documentation explicitly state that they 
00557 // support static_cast between void * and function pointers.
00558 
00559 class DelegateMemento {
00560 public: // my modification to allow for access -cat
00561     // the data is protected, not private, because many
00562     // compilers have problems with template friends.
00563     typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.
00564     detail::GenericClass *m_pthis;
00565     GenericMemFuncType m_pFunction;
00566 
00567 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00568     typedef void (*GenericFuncPtr)(); // arbitrary code pointer
00569     GenericFuncPtr m_pStaticFunction;
00570 #endif
00571 
00572 public:
00573 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00574     DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
00575     void clear() {
00576         m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
00577     }
00578 #else
00579     DelegateMemento() : m_pthis(0), m_pFunction(0) {};
00580     void clear() {    m_pthis=0; m_pFunction=0;    }
00581 #endif
00582 public:
00583 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00584     inline bool IsEqual (const DelegateMemento &x) const{
00585         // We have to cope with the static function pointers as a special case
00586         if (m_pFunction!=x.m_pFunction) return false;
00587         // the static function ptrs must either both be equal, or both be 0.
00588         if (m_pStaticFunction!=x.m_pStaticFunction) return false;
00589         if (m_pStaticFunction!=0) return m_pthis==x.m_pthis;
00590         else return true;
00591     }
00592 #else // Evil Method
00593     inline bool IsEqual (const DelegateMemento &x) const{
00594         return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
00595     }
00596 #endif
00597     // Provide a strict weak ordering for DelegateMementos.
00598     inline bool IsLess(const DelegateMemento &right) const {
00599         // deal with static function pointers first
00600 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00601         if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) 
00602                 return m_pStaticFunction < right.m_pStaticFunction;
00603 #endif
00604         if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis;
00605     // There are no ordering operators for member function pointers, 
00606     // but we can fake one by comparing each byte. The resulting ordering is
00607     // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
00608         return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
00609 
00610     }
00611     // BUGFIX (Mar 2005):
00612     // We can't just compare m_pFunction because on Metrowerks,
00613     // m_pFunction can be zero even if the delegate is not empty!
00614     inline bool operator ! () const        // Is it bound to anything?
00615     { return m_pthis==0 && m_pFunction==0; }
00616     inline bool empty() const        // Is it bound to anything?
00617     { return m_pthis==0 && m_pFunction==0; }
00618 public:
00619     DelegateMemento & operator = (const DelegateMemento &right)  {
00620         SetMementoFrom(right); 
00621         return *this;
00622     }
00623     inline bool operator <(const DelegateMemento &right) {
00624         return IsLess(right);
00625     }
00626     inline bool operator >(const DelegateMemento &right) {
00627         return right.IsLess(*this);
00628     }
00629     DelegateMemento (const DelegateMemento &right)  : 
00630         m_pFunction(right.m_pFunction), m_pthis(right.m_pthis)
00631 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00632         , m_pStaticFunction (right.m_pStaticFunction)
00633 #endif
00634         {}
00635 protected:
00636     void SetMementoFrom(const DelegateMemento &right)  {
00637         m_pFunction = right.m_pFunction;
00638         m_pthis = right.m_pthis;
00639 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00640         m_pStaticFunction = right.m_pStaticFunction;
00641 #endif
00642     }
00643 };
00644 
00645 
00646 //                        ClosurePtr<>
00647 //
00648 // A private wrapper class that adds function signatures to DelegateMemento.
00649 // It's the class that does most of the actual work.
00650 // The signatures are specified by:
00651 // GenericMemFunc: must be a type of GenericClass member function pointer. 
00652 // StaticFuncPtr:  must be a type of function pointer with the same signature 
00653 //                 as GenericMemFunc.
00654 // UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
00655 //                 where it never returns void (returns DefaultVoid instead).
00656 
00657 // An outer class, FastDelegateN<>, handles the invoking and creates the
00658 // necessary typedefs.
00659 // This class does everything else.
00660 
00661 namespace detail {
00662 
00663 template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
00664 class ClosurePtr : public DelegateMemento {
00665 public:
00666     // These functions are for setting the delegate to a member function.
00667 
00668     // Here's the clever bit: we convert an arbitrary member function into a 
00669     // standard form. XMemFunc should be a member function of class X, but I can't 
00670     // enforce that here. It needs to be enforced by the wrapper class.
00671     template < class X, class XMemFunc >
00672     inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) {
00673         m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
00674             ::Convert(pthis, function_to_bind, m_pFunction);
00675 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00676         m_pStaticFunction = 0;
00677 #endif
00678     }
00679     // For const member functions, we only need a const class pointer.
00680     // Since we know that the member function is const, it's safe to 
00681     // remove the const qualifier from the 'this' pointer with a const_cast.
00682     // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
00683     template < class X, class XMemFunc>
00684     inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) {
00685         m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
00686             ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
00687 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00688         m_pStaticFunction = 0;
00689 #endif
00690     }
00691 #ifdef FASTDELEGATE_GCC_BUG_8271    // At present, GCC doesn't recognize constness of MFPs in templates
00692     template < class X, class XMemFunc>
00693     inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) {
00694         bindconstmemfunc(pthis, function_to_bind);
00695 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00696         m_pStaticFunction = 0;
00697 #endif
00698     }
00699 #endif
00700     // These functions are required for invoking the stored function
00701     inline GenericClass *GetClosureThis() const { return m_pthis; }
00702     inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
00703 
00704 // There are a few ways of dealing with static function pointers.
00705 // There's a standard-compliant, but tricky method.
00706 // There's also a straightforward hack, that won't work on DOS compilers using the
00707 // medium memory model. It's so evil that I can't recommend it, but I've
00708 // implemented it anyway because it produces very nice asm code.
00709 
00710 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00711 
00712 //                ClosurePtr<> - Safe version
00713 //
00714 // This implementation is standard-compliant, but a bit tricky.
00715 // I store the function pointer inside the class, and the delegate then
00716 // points to itself. Whenever the delegate is copied, these self-references
00717 // must be transformed, and this complicates the = and == operators.
00718 public:
00719     // The next two functions are for operator ==, =, and the copy constructor.
00720     // We may need to convert the m_pthis pointers, so that
00721     // they remain as self-references.
00722     template< class DerivedClass >
00723     inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) {
00724         SetMementoFrom(x);
00725         if (m_pStaticFunction!=0) {
00726             // transform self references...
00727             m_pthis=reinterpret_cast<GenericClass *>(pParent);
00728         }
00729     }
00730     // For static functions, the 'static_function_invoker' class in the parent 
00731     // will be called. The parent then needs to call GetStaticFunction() to find out 
00732     // the actual function to invoke.
00733     template < class DerivedClass, class ParentInvokerSig >
00734     inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
00735                 StaticFuncPtr function_to_bind ) {
00736         if (function_to_bind==0) { // cope with assignment to 0
00737             m_pFunction=0;
00738         } else { 
00739             bindmemfunc(pParent, static_function_invoker);
00740         }
00741         m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
00742     }
00743     inline UnvoidStaticFuncPtr GetStaticFunction() const { 
00744         return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction); 
00745     }
00746 #else
00747 
00748 //                ClosurePtr<> - Evil version
00749 //
00750 // For compilers where data pointers are at least as big as code pointers, it is 
00751 // possible to store the function pointer in the this pointer, using another 
00752 // horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
00753 // speeds up comparison and assignment. If C++ provided direct language support
00754 // for delegates, they would produce asm code that was almost identical to this.
00755 // Note that the Sun C++ and MSVC documentation explicitly state that they 
00756 // support static_cast between void * and function pointers.
00757 
00758     template< class DerivedClass >
00759     inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) {
00760         SetMementoFrom(right);
00761     }
00762     // For static functions, the 'static_function_invoker' class in the parent 
00763     // will be called. The parent then needs to call GetStaticFunction() to find out 
00764     // the actual function to invoke.
00765     // ******** EVIL, EVIL CODE! *******
00766     template <     class DerivedClass, class ParentInvokerSig>
00767     inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
00768                 StaticFuncPtr function_to_bind) {
00769         if (function_to_bind==0) { // cope with assignment to 0
00770             m_pFunction=0;
00771         } else { 
00772            // We'll be ignoring the 'this' pointer, but we need to make sure we pass
00773            // a valid value to bindmemfunc().
00774             bindmemfunc(pParent, static_function_invoker);
00775         }
00776 
00777         // WARNING! Evil hack. We store the function in the 'this' pointer!
00778         // Ensure that there's a compilation failure if function pointers 
00779         // and data pointers have different sizes.
00780         // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
00781         typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
00782         m_pthis = horrible_cast<GenericClass *>(function_to_bind);
00783         // MSVC, SunC++ and DMC accept the following (non-standard) code:
00784 //        m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
00785         // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
00786 //        m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
00787     }
00788     // ******** EVIL, EVIL CODE! *******
00789     // This function will be called with an invalid 'this' pointer!!
00790     // We're just returning the 'this' pointer, converted into
00791     // a function pointer!
00792     inline UnvoidStaticFuncPtr GetStaticFunction() const {
00793         // Ensure that there's a compilation failure if function pointers 
00794         // and data pointers have different sizes.
00795         // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
00796         typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
00797         return horrible_cast<UnvoidStaticFuncPtr>(this);
00798     }
00799 #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00800 
00801     // Does the closure contain this static function?
00802     inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){
00803         if (funcptr==0) return empty(); 
00804     // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
00805     // value that is not equal to any valid function pointer.
00806         else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
00807     }
00808 };
00809 
00810 
00811 } // namespace detail
00812 
00814 //                        Fast Delegates, part 3:
00815 //
00816 //                Wrapper classes to ensure type safety
00817 //
00819 
00820 
00821 // Once we have the member function conversion templates, it's easy to make the
00822 // wrapper classes. So that they will work with as many compilers as possible, 
00823 // the classes are of the form
00824 //   FastDelegate3<int, char *, double>
00825 // They can cope with any combination of parameters. The max number of parameters
00826 // allowed is 8, but it is trivial to increase this limit.
00827 // Note that we need to treat const member functions seperately.
00828 // All this class does is to enforce type safety, and invoke the delegate with
00829 // the correct list of parameters.
00830 
00831 // Because of the weird rule about the class of derived member function pointers,
00832 // you sometimes need to apply a downcast to the 'this' pointer.
00833 // This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below. 
00834 // If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
00835 // without this trick you'd need to write:
00836 //        MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
00837 // but with the trick you can write
00838 //        MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
00839 
00840 // RetType is the type the compiler uses in compiling the template. For VC6,
00841 // it cannot be void. DesiredRetType is the real type which is returned from
00842 // all of the functions. It can be void.
00843 
00844 // Implicit conversion to "bool" is achieved using the safe_bool idiom,
00845 // using member data pointers (MDP). This allows "if (dg)..." syntax
00846 // Because some compilers (eg codeplay) don't have a unique value for a zero
00847 // MDP, an extra padding member is added to the SafeBool struct.
00848 // Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
00849 // in that case the static function constructor is not made explicit; this
00850 // allows "if (dg==0) ..." to compile.
00851 
00852 //N=0
00853 template<class RetType=detail::DefaultVoid>
00854 class FastDelegate0 {
00855 private:
00856     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
00857     typedef DesiredRetType (*StaticFunctionPtr)();
00858     typedef RetType (*UnvoidStaticFunctionPtr)();
00859     typedef RetType (detail::GenericClass::*GenericMemFn)();
00860     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00861     ClosureType m_Closure;
00862 public:
00863     // Typedefs to aid generic programming
00864     typedef FastDelegate0 type;
00865 
00866     // Construction and comparison functions
00867     FastDelegate0() { clear(); }
00868     FastDelegate0(const FastDelegate0 &x) {
00869         m_Closure.CopyFrom(this, x.m_Closure); }
00870     void operator = (const FastDelegate0 &x)  {
00871         m_Closure.CopyFrom(this, x.m_Closure); }
00872     bool operator ==(const FastDelegate0 &x) const {
00873         return m_Closure.IsEqual(x.m_Closure);    }
00874     bool operator !=(const FastDelegate0 &x) const {
00875         return !m_Closure.IsEqual(x.m_Closure); }
00876     bool operator <(const FastDelegate0 &x) const {
00877         return m_Closure.IsLess(x.m_Closure);    }
00878     bool operator >(const FastDelegate0 &x) const {
00879         return x.m_Closure.IsLess(m_Closure);    }
00880     // Binding to non-const member functions
00881     template < class X, class Y >
00882     FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) {
00883         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
00884     template < class X, class Y >
00885     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) {
00886         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
00887     // Binding to const member functions.
00888     template < class X, class Y >
00889     FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
00890         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
00891     template < class X, class Y >
00892     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
00893         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
00894     // Static functions. We convert them into a member function call.
00895     // This constructor also provides implicit conversion
00896     FastDelegate0(DesiredRetType (*function_to_bind)() ) {
00897         bind(function_to_bind);    }
00898     // for efficiency, prevent creation of a temporary
00899     void operator = (DesiredRetType (*function_to_bind)() ) {
00900         bind(function_to_bind);    }
00901     inline void bind(DesiredRetType (*function_to_bind)()) {
00902         m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, 
00903             function_to_bind); }
00904     // Invoke the delegate
00905     RetType operator() () const {
00906     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); }
00907     // Implicit conversion to "bool" using the safe_bool idiom
00908 private:
00909     typedef struct SafeBoolStruct {
00910         int a_data_pointer_to_this_is_0_on_buggy_compilers;
00911         StaticFunctionPtr m_nonzero;
00912     } UselessTypedef;
00913     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
00914 public:
00915     operator unspecified_bool_type() const {
00916         return empty()? 0: &SafeBoolStruct::m_nonzero;
00917     }
00918     // necessary to allow ==0 to work despite the safe_bool idiom
00919     inline bool operator==(StaticFunctionPtr funcptr) {
00920         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
00921     inline bool operator!=(StaticFunctionPtr funcptr) { 
00922         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
00923     inline bool operator ! () const    {    // Is it bound to anything?
00924             return !m_Closure; }
00925     inline bool empty() const    {
00926             return !m_Closure; }
00927     void clear() { m_Closure.clear();}
00928     // Conversion to and from the DelegateMemento storage class
00929     const DelegateMemento & GetMemento() { return m_Closure; }
00930     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
00931 
00932 private:    // Invoker for static functions
00933     RetType InvokeStaticFunction() const {
00934     return (*(m_Closure.GetStaticFunction()))(); }
00935 };
00936 
00937 //N=1
00938 template<class Param1, class RetType=detail::DefaultVoid>
00939 class FastDelegate1 {
00940 private:
00941     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
00942     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
00943     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
00944     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1);
00945     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00946     ClosureType m_Closure;
00947 public:
00948     // Typedefs to aid generic programming
00949     typedef FastDelegate1 type;
00950 
00951     // Construction and comparison functions
00952     FastDelegate1() { clear(); }
00953     FastDelegate1(const FastDelegate1 &x) {
00954         m_Closure.CopyFrom(this, x.m_Closure); }
00955     void operator = (const FastDelegate1 &x)  {
00956         m_Closure.CopyFrom(this, x.m_Closure); }
00957     bool operator ==(const FastDelegate1 &x) const {
00958         return m_Closure.IsEqual(x.m_Closure);    }
00959     bool operator !=(const FastDelegate1 &x) const {
00960         return !m_Closure.IsEqual(x.m_Closure); }
00961     bool operator <(const FastDelegate1 &x) const {
00962         return m_Closure.IsLess(x.m_Closure);    }
00963     bool operator >(const FastDelegate1 &x) const {
00964         return x.m_Closure.IsLess(m_Closure);    }
00965     // Binding to non-const member functions
00966     template < class X, class Y >
00967     FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) {
00968         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
00969     template < class X, class Y >
00970     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) {
00971         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
00972     // Binding to const member functions.
00973     template < class X, class Y >
00974     FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
00975         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
00976     template < class X, class Y >
00977     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
00978         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
00979     // Static functions. We convert them into a member function call.
00980     // This constructor also provides implicit conversion
00981     FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) {
00982         bind(function_to_bind);    }
00983     // for efficiency, prevent creation of a temporary
00984     void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) {
00985         bind(function_to_bind);    }
00986     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) {
00987         m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, 
00988             function_to_bind); }
00989     // Invoke the delegate
00990     RetType operator() (Param1 p1) const {
00991     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); }
00992     // Implicit conversion to "bool" using the safe_bool idiom
00993 private:
00994     typedef struct SafeBoolStruct {
00995         int a_data_pointer_to_this_is_0_on_buggy_compilers;
00996         StaticFunctionPtr m_nonzero;
00997     } UselessTypedef;
00998     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
00999 public:
01000     operator unspecified_bool_type() const {
01001         return empty()? 0: &SafeBoolStruct::m_nonzero;
01002     }
01003     // necessary to allow ==0 to work despite the safe_bool idiom
01004     inline bool operator==(StaticFunctionPtr funcptr) {
01005         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01006     inline bool operator!=(StaticFunctionPtr funcptr) { 
01007         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01008     inline bool operator ! () const    {    // Is it bound to anything?
01009             return !m_Closure; }
01010     inline bool empty() const    {
01011             return !m_Closure; }
01012     void clear() { m_Closure.clear();}
01013     // Conversion to and from the DelegateMemento storage class
01014     const DelegateMemento & GetMemento() { return m_Closure; }
01015     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01016 
01017 private:    // Invoker for static functions
01018     RetType InvokeStaticFunction(Param1 p1) const {
01019     return (*(m_Closure.GetStaticFunction()))(p1); }
01020 };
01021 
01022 //N=2
01023 template<class Param1, class Param2, class RetType=detail::DefaultVoid>
01024 class FastDelegate2 {
01025 private:
01026     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01027     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
01028     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
01029     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
01030     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01031     ClosureType m_Closure;
01032 public:
01033     // Typedefs to aid generic programming
01034     typedef FastDelegate2 type;
01035 
01036     // Construction and comparison functions
01037     FastDelegate2() { clear(); }
01038     FastDelegate2(const FastDelegate2 &x) {
01039         m_Closure.CopyFrom(this, x.m_Closure); }
01040     void operator = (const FastDelegate2 &x)  {
01041         m_Closure.CopyFrom(this, x.m_Closure); }
01042     bool operator ==(const FastDelegate2 &x) const {
01043         return m_Closure.IsEqual(x.m_Closure);    }
01044     bool operator !=(const FastDelegate2 &x) const {
01045         return !m_Closure.IsEqual(x.m_Closure); }
01046     bool operator <(const FastDelegate2 &x) const {
01047         return m_Closure.IsLess(x.m_Closure);    }
01048     bool operator >(const FastDelegate2 &x) const {
01049         return x.m_Closure.IsLess(m_Closure);    }
01050     // Binding to non-const member functions
01051     template < class X, class Y >
01052     FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) {
01053         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01054     template < class X, class Y >
01055     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) {
01056         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01057     // Binding to const member functions.
01058     template < class X, class Y >
01059     FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
01060         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01061     template < class X, class Y >
01062     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
01063         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01064     // Static functions. We convert them into a member function call.
01065     // This constructor also provides implicit conversion
01066     FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
01067         bind(function_to_bind);    }
01068     // for efficiency, prevent creation of a temporary
01069     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
01070         bind(function_to_bind);    }
01071     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) {
01072         m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, 
01073             function_to_bind); }
01074     // Invoke the delegate
01075     RetType operator() (Param1 p1, Param2 p2) const {
01076     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); }
01077     // Implicit conversion to "bool" using the safe_bool idiom
01078 private:
01079     typedef struct SafeBoolStruct {
01080         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01081         StaticFunctionPtr m_nonzero;
01082     } UselessTypedef;
01083     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01084 public:
01085     operator unspecified_bool_type() const {
01086         return empty()? 0: &SafeBoolStruct::m_nonzero;
01087     }
01088     // necessary to allow ==0 to work despite the safe_bool idiom
01089     inline bool operator==(StaticFunctionPtr funcptr) {
01090         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01091     inline bool operator!=(StaticFunctionPtr funcptr) { 
01092         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01093     inline bool operator ! () const    {    // Is it bound to anything?
01094             return !m_Closure; }
01095     inline bool empty() const    {
01096             return !m_Closure; }
01097     void clear() { m_Closure.clear();}
01098     // Conversion to and from the DelegateMemento storage class
01099     const DelegateMemento & GetMemento() { return m_Closure; }
01100     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01101 
01102 private:    // Invoker for static functions
01103     RetType InvokeStaticFunction(Param1 p1, Param2 p2) const {
01104     return (*(m_Closure.GetStaticFunction()))(p1, p2); }
01105 };
01106 
01107 //N=3
01108 template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
01109 class FastDelegate3 {
01110 private:
01111     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01112     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
01113     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
01114     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
01115     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01116     ClosureType m_Closure;
01117 public:
01118     // Typedefs to aid generic programming
01119     typedef FastDelegate3 type;
01120 
01121     // Construction and comparison functions
01122     FastDelegate3() { clear(); }
01123     FastDelegate3(const FastDelegate3 &x) {
01124         m_Closure.CopyFrom(this, x.m_Closure); }
01125     void operator = (const FastDelegate3 &x)  {
01126         m_Closure.CopyFrom(this, x.m_Closure); }
01127     bool operator ==(const FastDelegate3 &x) const {
01128         return m_Closure.IsEqual(x.m_Closure);    }
01129     bool operator !=(const FastDelegate3 &x) const {
01130         return !m_Closure.IsEqual(x.m_Closure); }
01131     bool operator <(const FastDelegate3 &x) const {
01132         return m_Closure.IsLess(x.m_Closure);    }
01133     bool operator >(const FastDelegate3 &x) const {
01134         return x.m_Closure.IsLess(m_Closure);    }
01135     // Binding to non-const member functions
01136     template < class X, class Y >
01137     FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01138         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01139     template < class X, class Y >
01140     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
01141         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01142     // Binding to const member functions.
01143     template < class X, class Y >
01144     FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
01145         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01146     template < class X, class Y >
01147     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
01148         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01149     // Static functions. We convert them into a member function call.
01150     // This constructor also provides implicit conversion
01151     FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01152         bind(function_to_bind);    }
01153     // for efficiency, prevent creation of a temporary
01154     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01155         bind(function_to_bind);    }
01156     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
01157         m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, 
01158             function_to_bind); }
01159     // Invoke the delegate
01160     RetType operator() (Param1 p1, Param2 p2, Param3 p3) const {
01161     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); }
01162     // Implicit conversion to "bool" using the safe_bool idiom
01163 private:
01164     typedef struct SafeBoolStruct {
01165         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01166         StaticFunctionPtr m_nonzero;
01167     } UselessTypedef;
01168     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01169 public:
01170     operator unspecified_bool_type() const {
01171         return empty()? 0: &SafeBoolStruct::m_nonzero;
01172     }
01173     // necessary to allow ==0 to work despite the safe_bool idiom
01174     inline bool operator==(StaticFunctionPtr funcptr) {
01175         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01176     inline bool operator!=(StaticFunctionPtr funcptr) { 
01177         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01178     inline bool operator ! () const    {    // Is it bound to anything?
01179             return !m_Closure; }
01180     inline bool empty() const    {
01181             return !m_Closure; }
01182     void clear() { m_Closure.clear();}
01183     // Conversion to and from the DelegateMemento storage class
01184     const DelegateMemento & GetMemento() { return m_Closure; }
01185     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01186 
01187 private:    // Invoker for static functions
01188     RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const {
01189     return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); }
01190 };
01191 
01192 //N=4
01193 template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
01194 class FastDelegate4 {
01195 private:
01196     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01197     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01198     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01199     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01200     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01201     ClosureType m_Closure;
01202 public:
01203     // Typedefs to aid generic programming
01204     typedef FastDelegate4 type;
01205 
01206     // Construction and comparison functions
01207     FastDelegate4() { clear(); }
01208     FastDelegate4(const FastDelegate4 &x) {
01209         m_Closure.CopyFrom(this, x.m_Closure); }
01210     void operator = (const FastDelegate4 &x)  {
01211         m_Closure.CopyFrom(this, x.m_Closure); }
01212     bool operator ==(const FastDelegate4 &x) const {
01213         return m_Closure.IsEqual(x.m_Closure);    }
01214     bool operator !=(const FastDelegate4 &x) const {
01215         return !m_Closure.IsEqual(x.m_Closure); }
01216     bool operator <(const FastDelegate4 &x) const {
01217         return m_Closure.IsLess(x.m_Closure);    }
01218     bool operator >(const FastDelegate4 &x) const {
01219         return x.m_Closure.IsLess(m_Closure);    }
01220     // Binding to non-const member functions
01221     template < class X, class Y >
01222     FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01223         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01224     template < class X, class Y >
01225     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
01226         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01227     // Binding to const member functions.
01228     template < class X, class Y >
01229     FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
01230         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01231     template < class X, class Y >
01232     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
01233         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01234     // Static functions. We convert them into a member function call.
01235     // This constructor also provides implicit conversion
01236     FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01237         bind(function_to_bind);    }
01238     // for efficiency, prevent creation of a temporary
01239     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01240         bind(function_to_bind);    }
01241     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
01242         m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, 
01243             function_to_bind); }
01244     // Invoke the delegate
01245     RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
01246     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); }
01247     // Implicit conversion to "bool" using the safe_bool idiom
01248 private:
01249     typedef struct SafeBoolStruct {
01250         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01251         StaticFunctionPtr m_nonzero;
01252     } UselessTypedef;
01253     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01254 public:
01255     operator unspecified_bool_type() const {
01256         return empty()? 0: &SafeBoolStruct::m_nonzero;
01257     }
01258     // necessary to allow ==0 to work despite the safe_bool idiom
01259     inline bool operator==(StaticFunctionPtr funcptr) {
01260         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01261     inline bool operator!=(StaticFunctionPtr funcptr) { 
01262         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01263     inline bool operator ! () const    {    // Is it bound to anything?
01264             return !m_Closure; }
01265     inline bool empty() const    {
01266             return !m_Closure; }
01267     void clear() { m_Closure.clear();}
01268     // Conversion to and from the DelegateMemento storage class
01269     const DelegateMemento & GetMemento() { return m_Closure; }
01270     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01271 
01272 private:    // Invoker for static functions
01273     RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
01274     return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); }
01275 };
01276 
01277 //N=5
01278 template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
01279 class FastDelegate5 {
01280 private:
01281     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01282     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01283     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01284     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01285     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01286     ClosureType m_Closure;
01287 public:
01288     // Typedefs to aid generic programming
01289     typedef FastDelegate5 type;
01290 
01291     // Construction and comparison functions
01292     FastDelegate5() { clear(); }
01293     FastDelegate5(const FastDelegate5 &x) {
01294         m_Closure.CopyFrom(this, x.m_Closure); }
01295     void operator = (const FastDelegate5 &x)  {
01296         m_Closure.CopyFrom(this, x.m_Closure); }
01297     bool operator ==(const FastDelegate5 &x) const {
01298         return m_Closure.IsEqual(x.m_Closure);    }
01299     bool operator !=(const FastDelegate5 &x) const {
01300         return !m_Closure.IsEqual(x.m_Closure); }
01301     bool operator <(const FastDelegate5 &x) const {
01302         return m_Closure.IsLess(x.m_Closure);    }
01303     bool operator >(const FastDelegate5 &x) const {
01304         return x.m_Closure.IsLess(m_Closure);    }
01305     // Binding to non-const member functions
01306     template < class X, class Y >
01307     FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01308         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01309     template < class X, class Y >
01310     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
01311         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01312     // Binding to const member functions.
01313     template < class X, class Y >
01314     FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
01315         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01316     template < class X, class Y >
01317     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
01318         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01319     // Static functions. We convert them into a member function call.
01320     // This constructor also provides implicit conversion
01321     FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01322         bind(function_to_bind);    }
01323     // for efficiency, prevent creation of a temporary
01324     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01325         bind(function_to_bind);    }
01326     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
01327         m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, 
01328             function_to_bind); }
01329     // Invoke the delegate
01330     RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
01331     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); }
01332     // Implicit conversion to "bool" using the safe_bool idiom
01333 private:
01334     typedef struct SafeBoolStruct {
01335         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01336         StaticFunctionPtr m_nonzero;
01337     } UselessTypedef;
01338     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01339 public:
01340     operator unspecified_bool_type() const {
01341         return empty()? 0: &SafeBoolStruct::m_nonzero;
01342     }
01343     // necessary to allow ==0 to work despite the safe_bool idiom
01344     inline bool operator==(StaticFunctionPtr funcptr) {
01345         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01346     inline bool operator!=(StaticFunctionPtr funcptr) { 
01347         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01348     inline bool operator ! () const    {    // Is it bound to anything?
01349             return !m_Closure; }
01350     inline bool empty() const    {
01351             return !m_Closure; }
01352     void clear() { m_Closure.clear();}
01353     // Conversion to and from the DelegateMemento storage class
01354     const DelegateMemento & GetMemento() { return m_Closure; }
01355     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01356 
01357 private:    // Invoker for static functions
01358     RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
01359     return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); }
01360 };
01361 
01362 //N=6
01363 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
01364 class FastDelegate6 {
01365 private:
01366     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01367     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01368     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01369     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01370     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01371     ClosureType m_Closure;
01372 public:
01373     // Typedefs to aid generic programming
01374     typedef FastDelegate6 type;
01375 
01376     // Construction and comparison functions
01377     FastDelegate6() { clear(); }
01378     FastDelegate6(const FastDelegate6 &x) {
01379         m_Closure.CopyFrom(this, x.m_Closure); }
01380     void operator = (const FastDelegate6 &x)  {
01381         m_Closure.CopyFrom(this, x.m_Closure); }
01382     bool operator ==(const FastDelegate6 &x) const {
01383         return m_Closure.IsEqual(x.m_Closure);    }
01384     bool operator !=(const FastDelegate6 &x) const {
01385         return !m_Closure.IsEqual(x.m_Closure); }
01386     bool operator <(const FastDelegate6 &x) const {
01387         return m_Closure.IsLess(x.m_Closure);    }
01388     bool operator >(const FastDelegate6 &x) const {
01389         return x.m_Closure.IsLess(m_Closure);    }
01390     // Binding to non-const member functions
01391     template < class X, class Y >
01392     FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01393         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01394     template < class X, class Y >
01395     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
01396         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01397     // Binding to const member functions.
01398     template < class X, class Y >
01399     FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
01400         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01401     template < class X, class Y >
01402     inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
01403         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01404     // Static functions. We convert them into a member function call.
01405     // This constructor also provides implicit conversion
01406     FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01407         bind(function_to_bind);    }
01408     // for efficiency, prevent creation of a temporary
01409     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01410         bind(function_to_bind);    }
01411     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
01412         m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, 
01413             function_to_bind); }
01414     // Invoke the delegate
01415     RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
01416     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); }
01417     // Implicit conversion to "bool" using the safe_bool idiom
01418 private:
01419     typedef struct SafeBoolStruct {
01420         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01421         StaticFunctionPtr m_nonzero;
01422     } UselessTypedef;
01423     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01424 public:
01425     operator unspecified_bool_type() const {
01426         return empty()? 0: &SafeBoolStruct::m_nonzero;
01427     }
01428     // necessary to allow ==0 to work despite the safe_bool idiom
01429     inline bool operator==(StaticFunctionPtr funcptr) {
01430         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01431     inline bool operator!=(StaticFunctionPtr funcptr) { 
01432         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01433     inline bool operator ! () const    {    // Is it bound to anything?
01434             return !m_Closure; }
01435     inline bool empty() const    {
01436             return !m_Closure; }
01437     void clear() { m_Closure.clear();}
01438     // Conversion to and from the DelegateMemento storage class
01439     const DelegateMemento & GetMemento() { return m_Closure; }
01440     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01441 
01442 private:    // Invoker for static functions
01443     RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
01444     return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); }
01445 };
01446 
01447 //N=7
01448 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
01449 class FastDelegate7 {
01450 private:
01451     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01452     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01453     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01454     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01455     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01456     ClosureType m_Closure;
01457 public:
01458     // Typedefs to aid generic programming
01459     typedef FastDelegate7 type;
01460 
01461     // Construction and comparison functions
01462     FastDelegate7() { clear(); }
01463     FastDelegate7(const FastDelegate7 &x) {
01464         m_Closure.CopyFrom(this, x.m_Closure); }
01465     void operator = (const FastDelegate7 &x)  {
01466         m_Closure.CopyFrom(this, x.m_Closure); }
01467     bool operator ==(const FastDelegate7 &x) const {
01468         return m_Closure.IsEqual(x.m_Closure);    }
01469     bool operator !=(const FastDelegate7 &x) const {
01470         return !m_Closure.IsEqual(x.m_Closure); }
01471     bool operator <(const FastDelegate7 &x) const {
01472         return m_Closure.IsLess(x.m_Closure);    }
01473     bool operator >(const FastDelegate7 &x) const {
01474         return x.m_Closure.IsLess(m_Closure);    }
01475     // Binding to non-const member functions
01476     template < class X, class Y >
01477     FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01478         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01479     template < class X, class Y >
01480     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
01481         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01482     // Binding to const member functions.
01483     template < class X, class Y >
01484     FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
01485         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01486     template < class X, class Y >
01487     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) {
01488         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01489     // Static functions. We convert them into a member function call.
01490     // This constructor also provides implicit conversion
01491     FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01492         bind(function_to_bind);    }
01493     // for efficiency, prevent creation of a temporary
01494     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01495         bind(function_to_bind);    }
01496     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
01497         m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, 
01498             function_to_bind); }
01499     // Invoke the delegate
01500     RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
01501     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); }
01502     // Implicit conversion to "bool" using the safe_bool idiom
01503 private:
01504     typedef struct SafeBoolStruct {
01505         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01506         StaticFunctionPtr m_nonzero;
01507     } UselessTypedef;
01508     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01509 public:
01510     operator unspecified_bool_type() const {
01511         return empty()? 0: &SafeBoolStruct::m_nonzero;
01512     }
01513     // necessary to allow ==0 to work despite the safe_bool idiom
01514     inline bool operator==(StaticFunctionPtr funcptr) {
01515         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01516     inline bool operator!=(StaticFunctionPtr funcptr) { 
01517         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01518     inline bool operator ! () const    {    // Is it bound to anything?
01519             return !m_Closure; }
01520     inline bool empty() const    {
01521             return !m_Closure; }
01522     void clear() { m_Closure.clear();}
01523     // Conversion to and from the DelegateMemento storage class
01524     const DelegateMemento & GetMemento() { return m_Closure; }
01525     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01526 
01527 private:    // Invoker for static functions
01528     RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
01529     return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); }
01530 };
01531 
01532 //N=8
01533 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
01534 class FastDelegate8 {
01535 private:
01536     typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01537     typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01538     typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01539     typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01540     typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01541     ClosureType m_Closure;
01542 public:
01543     // Typedefs to aid generic programming
01544     typedef FastDelegate8 type;
01545 
01546     // Construction and comparison functions
01547     FastDelegate8() { clear(); }
01548     FastDelegate8(const FastDelegate8 &x) {
01549         m_Closure.CopyFrom(this, x.m_Closure); }
01550     void operator = (const FastDelegate8 &x)  {
01551         m_Closure.CopyFrom(this, x.m_Closure); }
01552     bool operator ==(const FastDelegate8 &x) const {
01553         return m_Closure.IsEqual(x.m_Closure);    }
01554     bool operator !=(const FastDelegate8 &x) const {
01555         return !m_Closure.IsEqual(x.m_Closure); }
01556     bool operator <(const FastDelegate8 &x) const {
01557         return m_Closure.IsLess(x.m_Closure);    }
01558     bool operator >(const FastDelegate8 &x) const {
01559         return x.m_Closure.IsLess(m_Closure);    }
01560     // Binding to non-const member functions
01561     template < class X, class Y >
01562     FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01563         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01564     template < class X, class Y >
01565     inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
01566         m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);    }
01567     // Binding to const member functions.
01568     template < class X, class Y >
01569     FastDelegate8(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) {
01570         m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);    }
01571     template < class X, class Y >
01572     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) {
01573         m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);    }
01574     // Static functions. We convert them into a member function call.
01575     // This constructor also provides implicit conversion
01576     FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01577         bind(function_to_bind);    }
01578     // for efficiency, prevent creation of a temporary
01579     void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01580         bind(function_to_bind);    }
01581     inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
01582         m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, 
01583             function_to_bind); }
01584     // Invoke the delegate
01585     RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
01586     return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); }
01587     // Implicit conversion to "bool" using the safe_bool idiom
01588 private:
01589     typedef struct SafeBoolStruct {
01590         int a_data_pointer_to_this_is_0_on_buggy_compilers;
01591         StaticFunctionPtr m_nonzero;
01592     } UselessTypedef;
01593     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01594 public:
01595     operator unspecified_bool_type() const {
01596         return empty()? 0: &SafeBoolStruct::m_nonzero;
01597     }
01598     // necessary to allow ==0 to work despite the safe_bool idiom
01599     inline bool operator==(StaticFunctionPtr funcptr) {
01600         return m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01601     inline bool operator!=(StaticFunctionPtr funcptr) { 
01602         return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01603     inline bool operator ! () const    {    // Is it bound to anything?
01604             return !m_Closure; }
01605     inline bool empty() const    {
01606             return !m_Closure; }
01607     void clear() { m_Closure.clear();}
01608     // Conversion to and from the DelegateMemento storage class
01609     const DelegateMemento & GetMemento() { return m_Closure; }
01610     void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01611 
01612 private:    // Invoker for static functions
01613     RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
01614     return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); }
01615 };
01616 
01617 
01619 //                        Fast Delegates, part 4:
01620 // 
01621 //                FastDelegate<> class (Original author: Jody Hagins)
01622 //    Allows boost::function style syntax like:
01623 //            FastDelegate< double (int, long) >
01624 // instead of:
01625 //            FastDelegate2< int, long, double >
01626 //
01628 
01629 #ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
01630 
01631 // Declare FastDelegate as a class template.  It will be specialized
01632 // later for all number of arguments.
01633 template <typename Signature>
01634 class FastDelegate;
01635 
01636 //N=0
01637 // Specialization to allow use of
01638 // FastDelegate< R (  ) >
01639 // instead of 
01640 // FastDelegate0 < R >
01641 template<typename R>
01642 class FastDelegate< R (  ) >
01643   // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
01644   : public FastDelegate0 < R >
01645 {
01646 public:
01647   // Make using the base type a bit easier via typedef.
01648   typedef FastDelegate0 < R > BaseType;
01649 
01650   // Allow users access to the specific type of this delegate.
01651   typedef FastDelegate SelfType;
01652 
01653   // Mimic the base class constructors.
01654   FastDelegate() : BaseType() { }
01655 
01656   template < class X, class Y >
01657   FastDelegate(Y * pthis, 
01658     R (X::* function_to_bind)(  ))
01659     : BaseType(pthis, function_to_bind)  { }
01660 
01661   template < class X, class Y >
01662   FastDelegate(const Y *pthis,
01663       R (X::* function_to_bind)(  ) const)
01664     : BaseType(pthis, function_to_bind)
01665   {  }
01666 
01667   FastDelegate(R (*function_to_bind)(  ))
01668     : BaseType(function_to_bind)  { }
01669   void operator = (const BaseType &x)  {      
01670         *static_cast<BaseType*>(this) = x; }
01671 };
01672 
01673 //N=1
01674 // Specialization to allow use of
01675 // FastDelegate< R ( Param1 ) >
01676 // instead of 
01677 // FastDelegate1 < Param1, R >
01678 template<typename R, class Param1>
01679 class FastDelegate< R ( Param1 ) >
01680   // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
01681   : public FastDelegate1 < Param1, R >
01682 {
01683 public:
01684   // Make using the base type a bit easier via typedef.
01685   typedef FastDelegate1 < Param1, R > BaseType;
01686 
01687   // Allow users access to the specific type of this delegate.
01688   typedef FastDelegate SelfType;
01689 
01690   // Mimic the base class constructors.
01691   FastDelegate() : BaseType() { }
01692 
01693   template < class X, class Y >
01694   FastDelegate(Y * pthis, 
01695     R (X::* function_to_bind)( Param1 p1 ))
01696     : BaseType(pthis, function_to_bind)  { }
01697 
01698   template < class X, class Y >
01699   FastDelegate(const Y *pthis,
01700       R (X::* function_to_bind)( Param1 p1 ) const)
01701     : BaseType(pthis, function_to_bind)
01702   {  }
01703 
01704   FastDelegate(R (*function_to_bind)( Param1 p1 ))
01705     : BaseType(function_to_bind)  { }
01706   void operator = (const BaseType &x)  {      
01707         *static_cast<BaseType*>(this) = x; }
01708 };
01709 
01710 //N=2
01711 // Specialization to allow use of
01712 // FastDelegate< R ( Param1, Param2 ) >
01713 // instead of 
01714 // FastDelegate2 < Param1, Param2, R >
01715 template<typename R, class Param1, class Param2>
01716 class FastDelegate< R ( Param1, Param2 ) >
01717   // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
01718   : public FastDelegate2 < Param1, Param2, R >
01719 {
01720 public:
01721   // Make using the base type a bit easier via typedef.
01722   typedef FastDelegate2 < Param1, Param2, R > BaseType;
01723 
01724   // Allow users access to the specific type of this delegate.
01725   typedef FastDelegate SelfType;
01726 
01727   // Mimic the base class constructors.
01728   FastDelegate() : BaseType() { }
01729 
01730   template < class X, class Y >
01731   FastDelegate(Y * pthis, 
01732     R (X::* function_to_bind)( Param1 p1, Param2 p2 ))
01733     : BaseType(pthis, function_to_bind)  { }
01734 
01735   template < class X, class Y >
01736   FastDelegate(const Y *pthis,
01737       R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const)
01738     : BaseType(pthis, function_to_bind)
01739   {  }
01740 
01741   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 ))
01742     : BaseType(function_to_bind)  { }
01743   void operator = (const BaseType &x)  {      
01744         *static_cast<BaseType*>(this) = x; }
01745 };
01746 
01747 //N=3
01748 // Specialization to allow use of
01749 // FastDelegate< R ( Param1, Param2, Param3 ) >
01750 // instead of 
01751 // FastDelegate3 < Param1, Param2, Param3, R >
01752 template<typename R, class Param1, class Param2, class Param3>
01753 class FastDelegate< R ( Param1, Param2, Param3 ) >
01754   // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
01755   : public FastDelegate3 < Param1, Param2, Param3, R >
01756 {
01757 public:
01758   // Make using the base type a bit easier via typedef.
01759   typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType;
01760 
01761   // Allow users access to the specific type of this delegate.
01762   typedef FastDelegate SelfType;
01763 
01764   // Mimic the base class constructors.
01765   FastDelegate() : BaseType() { }
01766 
01767   template < class X, class Y >
01768   FastDelegate(Y * pthis, 
01769     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
01770     : BaseType(pthis, function_to_bind)  { }
01771 
01772   template < class X, class Y >
01773   FastDelegate(const Y *pthis,
01774       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const)
01775     : BaseType(pthis, function_to_bind)
01776   {  }
01777 
01778   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
01779     : BaseType(function_to_bind)  { }
01780   void operator = (const BaseType &x)  {      
01781         *static_cast<BaseType*>(this) = x; }
01782 };
01783 
01784 //N=4
01785 // Specialization to allow use of
01786 // FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
01787 // instead of 
01788 // FastDelegate4 < Param1, Param2, Param3, Param4, R >
01789 template<typename R, class Param1, class Param2, class Param3, class Param4>
01790 class FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
01791   // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
01792   : public FastDelegate4 < Param1, Param2, Param3, Param4, R >
01793 {
01794 public:
01795   // Make using the base type a bit easier via typedef.
01796   typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType;
01797 
01798   // Allow users access to the specific type of this delegate.
01799   typedef FastDelegate SelfType;
01800 
01801   // Mimic the base class constructors.
01802   FastDelegate() : BaseType() { }
01803 
01804   template < class X, class Y >
01805   FastDelegate(Y * pthis, 
01806     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
01807     : BaseType(pthis, function_to_bind)  { }
01808 
01809   template < class X, class Y >
01810   FastDelegate(const Y *pthis,
01811       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const)
01812     : BaseType(pthis, function_to_bind)
01813   {  }
01814 
01815   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
01816     : BaseType(function_to_bind)  { }
01817   void operator = (const BaseType &x)  {      
01818         *static_cast<BaseType*>(this) = x; }
01819 };
01820 
01821 //N=5
01822 // Specialization to allow use of
01823 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
01824 // instead of 
01825 // FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
01826 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
01827 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
01828   // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
01829   : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
01830 {
01831 public:
01832   // Make using the base type a bit easier via typedef.
01833   typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType;
01834 
01835   // Allow users access to the specific type of this delegate.
01836   typedef FastDelegate SelfType;
01837 
01838   // Mimic the base class constructors.
01839   FastDelegate() : BaseType() { }
01840 
01841   template < class X, class Y >
01842   FastDelegate(Y * pthis, 
01843     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
01844     : BaseType(pthis, function_to_bind)  { }
01845 
01846   template < class X, class Y >
01847   FastDelegate(const Y *pthis,
01848       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const)
01849     : BaseType(pthis, function_to_bind)
01850   {  }
01851 
01852   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
01853     : BaseType(function_to_bind)  { }
01854   void operator = (const BaseType &x)  {      
01855         *static_cast<BaseType*>(this) = x; }
01856 };
01857 
01858 //N=6
01859 // Specialization to allow use of
01860 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
01861 // instead of 
01862 // FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
01863 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
01864 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
01865   // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
01866   : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
01867 {
01868 public:
01869   // Make using the base type a bit easier via typedef.
01870   typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType;
01871 
01872   // Allow users access to the specific type of this delegate.
01873   typedef FastDelegate SelfType;
01874 
01875   // Mimic the base class constructors.
01876   FastDelegate() : BaseType() { }
01877 
01878   template < class X, class Y >
01879   FastDelegate(Y * pthis, 
01880     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
01881     : BaseType(pthis, function_to_bind)  { }
01882 
01883   template < class X, class Y >
01884   FastDelegate(const Y *pthis,
01885       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const)
01886     : BaseType(pthis, function_to_bind)
01887   {  }
01888 
01889   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
01890     : BaseType(function_to_bind)  { }
01891   void operator = (const BaseType &x)  {      
01892         *static_cast<BaseType*>(this) = x; }
01893 };
01894 
01895 //N=7
01896 // Specialization to allow use of
01897 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
01898 // instead of 
01899 // FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
01900 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
01901 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
01902   // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
01903   : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
01904 {
01905 public:
01906   // Make using the base type a bit easier via typedef.
01907   typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType;
01908 
01909   // Allow users access to the specific type of this delegate.
01910   typedef FastDelegate SelfType;
01911 
01912   // Mimic the base class constructors.
01913   FastDelegate() : BaseType() { }
01914 
01915   template < class X, class Y >
01916   FastDelegate(Y * pthis, 
01917     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
01918     : BaseType(pthis, function_to_bind)  { }
01919 
01920   template < class X, class Y >
01921   FastDelegate(const Y *pthis,
01922       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const)
01923     : BaseType(pthis, function_to_bind)
01924   {  }
01925 
01926   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
01927     : BaseType(function_to_bind)  { }
01928   void operator = (const BaseType &x)  {      
01929         *static_cast<BaseType*>(this) = x; }
01930 };
01931 
01932 //N=8
01933 // Specialization to allow use of
01934 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
01935 // instead of 
01936 // FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
01937 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
01938 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
01939   // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
01940   : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
01941 {
01942 public:
01943   // Make using the base type a bit easier via typedef.
01944   typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType;
01945 
01946   // Allow users access to the specific type of this delegate.
01947   typedef FastDelegate SelfType;
01948 
01949   // Mimic the base class constructors.
01950   FastDelegate() : BaseType() { }
01951 
01952   template < class X, class Y >
01953   FastDelegate(Y * pthis, 
01954     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
01955     : BaseType(pthis, function_to_bind)  { }
01956 
01957   template < class X, class Y >
01958   FastDelegate(const Y *pthis,
01959       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const)
01960     : BaseType(pthis, function_to_bind)
01961   {  }
01962 
01963   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
01964     : BaseType(function_to_bind)  { }
01965   void operator = (const BaseType &x)  {      
01966         *static_cast<BaseType*>(this) = x; }
01967 };
01968 
01969 
01970 #endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
01971 
01973 //                        Fast Delegates, part 5:
01974 //
01975 //                MakeDelegate() helper function
01976 //
01977 //            MakeDelegate(&x, &X::func) returns a fastdelegate of the type
01978 //            necessary for calling x.func() with the correct number of arguments.
01979 //            This makes it possible to eliminate many typedefs from user code.
01980 //
01982 
01983 // Also declare overloads of a MakeDelegate() global function to 
01984 // reduce the need for typedefs.
01985 // We need seperate overloads for const and non-const member functions.
01986 // Also, because of the weird rule about the class of derived member function pointers,
01987 // implicit downcasts may need to be applied later to the 'this' pointer.
01988 // That's why two classes (X and Y) appear in the definitions. Y must be implicitly
01989 // castable to X.
01990 
01991 // Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
01992 // GCC 3.2 and later won't compile this unless it's preceded by 'typename',
01993 // but VC6 doesn't allow 'typename' in this context.
01994 // So, I have to use a macro.
01995 
01996 #ifdef FASTDLGT_VC6
01997 #define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
01998 #else 
01999 #define FASTDLGT_RETTYPE RetType
02000 #endif
02001 
02002 //N=0
02003 template <class X, class Y, class RetType>
02004 FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)()) { 
02005     return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
02006 }
02007 
02008 template <class X, class Y, class RetType>
02009 FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)() const) { 
02010     return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
02011 }
02012 
02013 //N=1
02014 template <class X, class Y, class Param1, class RetType>
02015 FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { 
02016     return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
02017 }
02018 
02019 template <class X, class Y, class Param1, class RetType>
02020 FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { 
02021     return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
02022 }
02023 
02024 //N=2
02025 template <class X, class Y, class Param1, class Param2, class RetType>
02026 FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { 
02027     return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
02028 }
02029 
02030 template <class X, class Y, class Param1, class Param2, class RetType>
02031 FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { 
02032     return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
02033 }
02034 
02035 //N=3
02036 template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
02037 FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { 
02038     return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
02039 }
02040 
02041 template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
02042 FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { 
02043     return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
02044 }
02045 
02046 //N=4
02047 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
02048 FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { 
02049     return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
02050 }
02051 
02052 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
02053 FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { 
02054     return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
02055 }
02056 
02057 //N=5
02058 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
02059 FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { 
02060     return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
02061 }
02062 
02063 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
02064 FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { 
02065     return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
02066 }
02067 
02068 //N=6
02069 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
02070 FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { 
02071     return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
02072 }
02073 
02074 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
02075 FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { 
02076     return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
02077 }
02078 
02079 //N=7
02080 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
02081 FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { 
02082     return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
02083 }
02084 
02085 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
02086 FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { 
02087     return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
02088 }
02089 
02090 //N=8
02091 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
02092 FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { 
02093     return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
02094 }
02095 
02096 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
02097 FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { 
02098     return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
02099 }
02100 
02101 
02102  // clean up after ourselves...
02103 #undef FASTDLGT_RETTYPE
02104 
02105 } // namespace fastdelegate
02106 
02107 #endif // !defined(FASTDELEGATE_H)
02108 

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net