libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/old/FastDelegate.hpp
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 protected: 
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         
00568 
00569 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00570         typedef void (*GenericFuncPtr)(); // arbitrary code pointer
00571         GenericFuncPtr m_pStaticFunction;
00572 #endif
00573 
00574 public:
00575 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00576         DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
00577         void clear() {
00578                 m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
00579         }
00580 #else
00581         DelegateMemento() : m_pthis(0), m_pFunction(0) {};
00582         void clear() {  m_pthis=0; m_pFunction=0;       }
00583 #endif
00584 public:
00585 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00586         inline bool IsEqual (const DelegateMemento &x) const{
00587             // We have to cope with the static function pointers as a special case
00588                 if (m_pFunction!=x.m_pFunction) return false;
00589                 // the static function ptrs must either both be equal, or both be 0.
00590                 if (m_pStaticFunction!=x.m_pStaticFunction) return false;
00591                 if (m_pStaticFunction!=0) return m_pthis==x.m_pthis;
00592                 else return true;
00593         }
00594 #else // Evil Method
00595         inline bool IsEqual (const DelegateMemento &x) const{
00596                 return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
00597         }
00598 #endif
00599         // Provide a strict weak ordering for DelegateMementos.
00600         inline bool IsLess(const DelegateMemento &right) const {
00601                 // deal with static function pointers first
00602 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00603                 if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) 
00604                                 return m_pStaticFunction < right.m_pStaticFunction;
00605 #endif
00606                 if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis;
00607         // There are no ordering operators for member function pointers, 
00608         // but we can fake one by comparing each byte. The resulting ordering is
00609         // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
00610                 return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
00611 
00612         }
00613         // BUGFIX (Mar 2005):
00614         // We can't just compare m_pFunction because on Metrowerks,
00615         // m_pFunction can be zero even if the delegate is not empty!
00616         inline bool operator ! () const         // Is it bound to anything?
00617         { return m_pthis==0 && m_pFunction==0; }
00618         inline bool empty() const               // Is it bound to anything?
00619         { return m_pthis==0 && m_pFunction==0; }
00620 public:
00621         DelegateMemento & operator = (const DelegateMemento &right)  {
00622                 SetMementoFrom(right); 
00623                 return *this;
00624         }
00625         inline bool operator <(const DelegateMemento &right) {
00626                 return IsLess(right);
00627         }
00628         inline bool operator >(const DelegateMemento &right) {
00629                 return right.IsLess(*this);
00630         }
00631         DelegateMemento (const DelegateMemento &right)  : 
00632             m_pthis(right.m_pthis), m_pFunction(right.m_pFunction)
00633 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00634                 , m_pStaticFunction (right.m_pStaticFunction)
00635 #endif
00636                 {}
00637 protected:
00638         void SetMementoFrom(const DelegateMemento &right)  {
00639                 m_pFunction = right.m_pFunction;
00640                 m_pthis = right.m_pthis;
00641 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00642                 m_pStaticFunction = right.m_pStaticFunction;
00643 #endif
00644         }
00645 };
00646 
00647 
00648 //                                              ClosurePtr<>
00649 //
00650 // A private wrapper class that adds function signatures to DelegateMemento.
00651 // It's the class that does most of the actual work.
00652 // The signatures are specified by:
00653 // GenericMemFunc: must be a type of GenericClass member function pointer. 
00654 // StaticFuncPtr:  must be a type of function pointer with the same signature 
00655 //                 as GenericMemFunc.
00656 // UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
00657 //                 where it never returns void (returns DefaultVoid instead).
00658 
00659 // An outer class, FastDelegateN<>, handles the invoking and creates the
00660 // necessary typedefs.
00661 // This class does everything else.
00662 
00663 namespace detail {
00664 
00665 template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
00666 class ClosurePtr : public DelegateMemento {
00667 public:
00668         // These functions are for setting the delegate to a member function.
00669 
00670         // Here's the clever bit: we convert an arbitrary member function into a 
00671         // standard form. XMemFunc should be a member function of class X, but I can't 
00672         // enforce that here. It needs to be enforced by the wrapper class.
00673         template < class X, class XMemFunc >
00674         inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) {
00675                 m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
00676                         ::Convert(pthis, function_to_bind, m_pFunction);
00677 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00678                 m_pStaticFunction = 0;
00679 #endif
00680         }
00681         // For const member functions, we only need a const class pointer.
00682         // Since we know that the member function is const, it's safe to 
00683         // remove the const qualifier from the 'this' pointer with a const_cast.
00684         // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
00685         template < class X, class XMemFunc>
00686         inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) {
00687                 m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
00688                         ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
00689 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00690                 m_pStaticFunction = 0;
00691 #endif
00692         }
00693 #ifdef FASTDELEGATE_GCC_BUG_8271        // At present, GCC doesn't recognize constness of MFPs in templates
00694         template < class X, class XMemFunc>
00695         inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) {
00696                 bindconstmemfunc(pthis, function_to_bind);
00697 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00698                 m_pStaticFunction = 0;
00699 #endif
00700         }
00701 #endif
00702         // These functions are required for invoking the stored function
00703         inline GenericClass *GetClosureThis() const { return m_pthis; }
00704         inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
00705 
00706 // There are a few ways of dealing with static function pointers.
00707 // There's a standard-compliant, but tricky method.
00708 // There's also a straightforward hack, that won't work on DOS compilers using the
00709 // medium memory model. It's so evil that I can't recommend it, but I've
00710 // implemented it anyway because it produces very nice asm code.
00711 
00712 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00713 
00714 //                              ClosurePtr<> - Safe version
00715 //
00716 // This implementation is standard-compliant, but a bit tricky.
00717 // I store the function pointer inside the class, and the delegate then
00718 // points to itself. Whenever the delegate is copied, these self-references
00719 // must be transformed, and this complicates the = and == operators.
00720 public:
00721         // The next two functions are for operator ==, =, and the copy constructor.
00722         // We may need to convert the m_pthis pointers, so that
00723         // they remain as self-references.
00724         template< class DerivedClass >
00725         inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) {
00726                 SetMementoFrom(x);
00727                 if (m_pStaticFunction!=0) {
00728                         // transform self references...
00729                         m_pthis=reinterpret_cast<GenericClass *>(pParent);
00730                 }
00731         }
00732         // For static functions, the 'static_function_invoker' class in the parent 
00733         // will be called. The parent then needs to call GetStaticFunction() to find out 
00734         // the actual function to invoke.
00735         template < class DerivedClass, class ParentInvokerSig >
00736         inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
00737                                 StaticFuncPtr function_to_bind ) {
00738                 if (function_to_bind==0) { // cope with assignment to 0
00739                         m_pFunction=0;
00740                 } else { 
00741                         bindmemfunc(pParent, static_function_invoker);
00742         }
00743                 m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
00744         }
00745         inline UnvoidStaticFuncPtr GetStaticFunction() const { 
00746                 return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction); 
00747         }
00748 #else
00749 
00750 //                              ClosurePtr<> - Evil version
00751 //
00752 // For compilers where data pointers are at least as big as code pointers, it is 
00753 // possible to store the function pointer in the this pointer, using another 
00754 // horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
00755 // speeds up comparison and assignment. If C++ provided direct language support
00756 // for delegates, they would produce asm code that was almost identical to this.
00757 // Note that the Sun C++ and MSVC documentation explicitly state that they 
00758 // support static_cast between void * and function pointers.
00759 
00760         template< class DerivedClass >
00761         inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) {
00762                 SetMementoFrom(right);
00763         }
00764         // For static functions, the 'static_function_invoker' class in the parent 
00765         // will be called. The parent then needs to call GetStaticFunction() to find out 
00766         // the actual function to invoke.
00767         // ******** EVIL, EVIL CODE! *******
00768         template <      class DerivedClass, class ParentInvokerSig>
00769         inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
00770                                 StaticFuncPtr function_to_bind) {
00771                 if (function_to_bind==0) { // cope with assignment to 0
00772                         m_pFunction=0;
00773                 } else { 
00774                    // We'll be ignoring the 'this' pointer, but we need to make sure we pass
00775                    // a valid value to bindmemfunc().
00776                         bindmemfunc(pParent, static_function_invoker);
00777         }
00778 
00779                 // WARNING! Evil hack. We store the function in the 'this' pointer!
00780                 // Ensure that there's a compilation failure if function pointers 
00781                 // and data pointers have different sizes.
00782                 // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
00783                 typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
00784                 m_pthis = horrible_cast<GenericClass *>(function_to_bind);
00785                 // MSVC, SunC++ and DMC accept the following (non-standard) code:
00786 //              m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
00787                 // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
00788 //              m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
00789         }
00790         // ******** EVIL, EVIL CODE! *******
00791         // This function will be called with an invalid 'this' pointer!!
00792         // We're just returning the 'this' pointer, converted into
00793         // a function pointer!
00794         inline UnvoidStaticFuncPtr GetStaticFunction() const {
00795                 // Ensure that there's a compilation failure if function pointers 
00796                 // and data pointers have different sizes.
00797                 // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
00798                 typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
00799                 return horrible_cast<UnvoidStaticFuncPtr>(this);
00800         }
00801 #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00802 
00803         // Does the closure contain this static function?
00804         inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){
00805                 if (funcptr==0) return empty(); 
00806         // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
00807         // value that is not equal to any valid function pointer.
00808                 else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
00809         }
00810 };
00811 
00812 
00813 } // namespace detail
00814 
00816 //                                              Fast Delegates, part 3:
00817 //
00818 //                              Wrapper classes to ensure type safety
00819 //
00821 
00822 
00823 // Once we have the member function conversion templates, it's easy to make the
00824 // wrapper classes. So that they will work with as many compilers as possible, 
00825 // the classes are of the form
00826 //   FastDelegate3<int, char *, double>
00827 // They can cope with any combination of parameters. The max number of parameters
00828 // allowed is 8, but it is trivial to increase this limit.
00829 // Note that we need to treat const member functions seperately.
00830 // All this class does is to enforce type safety, and invoke the delegate with
00831 // the correct list of parameters.
00832 
00833 // Because of the weird rule about the class of derived member function pointers,
00834 // you sometimes need to apply a downcast to the 'this' pointer.
00835 // This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below. 
00836 // If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
00837 // without this trick you'd need to write:
00838 //              MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
00839 // but with the trick you can write
00840 //              MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
00841 
00842 // RetType is the type the compiler uses in compiling the template. For VC6,
00843 // it cannot be void. DesiredRetType is the real type which is returned from
00844 // all of the functions. It can be void.
00845 
00846 // Implicit conversion to "bool" is achieved using the safe_bool idiom,
00847 // using member data pointers (MDP). This allows "if (dg)..." syntax
00848 // Because some compilers (eg codeplay) don't have a unique value for a zero
00849 // MDP, an extra padding member is added to the SafeBool struct.
00850 // Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
00851 // in that case the static function constructor is not made explicit; this
00852 // allows "if (dg==0) ..." to compile.
00853 
00854 //N=0
00855 template<class RetType=detail::DefaultVoid>
00856 class FastDelegate0 {
00857 private:
00858         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
00859         typedef DesiredRetType (*StaticFunctionPtr)();
00860         typedef RetType (*UnvoidStaticFunctionPtr)();
00861         typedef RetType (detail::GenericClass::*GenericMemFn)();
00862         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00863         ClosureType m_Closure;
00864 public:
00865         // Typedefs to aid generic programming
00866         typedef FastDelegate0 type;
00867 
00868         // Construction and comparison functions
00869         FastDelegate0() { clear(); }
00870         FastDelegate0(const FastDelegate0 &x) {
00871                 m_Closure.CopyFrom(this, x.m_Closure); }
00872         void operator = (const FastDelegate0 &x)  {
00873                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
00878         bool operator <(const FastDelegate0 &x) const {
00879                 return m_Closure.IsLess(x.m_Closure);   }
00880         bool operator >(const FastDelegate0 &x) const {
00881                 return x.m_Closure.IsLess(m_Closure);   }
00882         // Binding to non-const member functions
00883         template < class X, class Y >
00884         FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) {
00885                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
00886         template < class X, class Y >
00887         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) {
00888                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
00889         // Binding to const member functions.
00890         template < class X, class Y >
00891         FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
00892                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
00893         template < class X, class Y >
00894         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
00895                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
00896         // Static functions. We convert them into a member function call.
00897         // This constructor also provides implicit conversion
00898         FastDelegate0(DesiredRetType (*function_to_bind)() ) {
00899                 bind(function_to_bind); }
00900         // for efficiency, prevent creation of a temporary
00901         void operator = (DesiredRetType (*function_to_bind)() ) {
00902                 bind(function_to_bind); }
00903         inline void bind(DesiredRetType (*function_to_bind)()) {
00904                 m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, 
00905                         function_to_bind); }
00906         // Invoke the delegate
00907         RetType operator() () const {
00908         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); }
00909         // Implicit conversion to "bool" using the safe_bool idiom
00910 private:
00911         typedef struct SafeBoolStruct {
00912                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
00913                 StaticFunctionPtr m_nonzero;
00914         } UselessTypedef;
00915     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
00916 public:
00917         operator unspecified_bool_type() const {
00918         return empty()? 0: &SafeBoolStruct::m_nonzero;
00919     }
00920         // necessary to allow ==0 to work despite the safe_bool idiom
00921         inline bool operator==(StaticFunctionPtr funcptr) {
00922                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
00923         inline bool operator!=(StaticFunctionPtr funcptr) { 
00924                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
00925         inline bool operator ! () const {       // Is it bound to anything?
00926                         return !m_Closure; }
00927         inline bool empty() const       {
00928                         return !m_Closure; }
00929         void clear() { m_Closure.clear();}
00930         // Conversion to and from the DelegateMemento storage class
00931         const DelegateMemento & GetMemento() { return m_Closure; }
00932         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
00933 
00934 private:        // Invoker for static functions
00935         RetType InvokeStaticFunction() const {
00936         return (*(m_Closure.GetStaticFunction()))(); }
00937 };
00938 
00939 //N=1
00940 template<class Param1, class RetType=detail::DefaultVoid>
00941 class FastDelegate1 {
00942 private:
00943         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
00944         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
00945         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
00946         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1);
00947         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00948         ClosureType m_Closure;
00949 public:
00950         // Typedefs to aid generic programming
00951         typedef FastDelegate1 type;
00952 
00953         // Construction and comparison functions
00954         FastDelegate1() { clear(); }
00955         FastDelegate1(const FastDelegate1 &x) {
00956                 m_Closure.CopyFrom(this, x.m_Closure); }
00957         void operator = (const FastDelegate1 &x)  {
00958                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
00963         bool operator <(const FastDelegate1 &x) const {
00964                 return m_Closure.IsLess(x.m_Closure);   }
00965         bool operator >(const FastDelegate1 &x) const {
00966                 return x.m_Closure.IsLess(m_Closure);   }
00967         // Binding to non-const member functions
00968         template < class X, class Y >
00969         FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) {
00970                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
00971         template < class X, class Y >
00972         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) {
00973                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
00974         // Binding to const member functions.
00975         template < class X, class Y >
00976         FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
00977                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
00978         template < class X, class Y >
00979         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
00980                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
00981         // Static functions. We convert them into a member function call.
00982         // This constructor also provides implicit conversion
00983         FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) {
00984                 bind(function_to_bind); }
00985         // for efficiency, prevent creation of a temporary
00986         void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) {
00987                 bind(function_to_bind); }
00988         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) {
00989                 m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, 
00990                         function_to_bind); }
00991         // Invoke the delegate
00992         RetType operator() (Param1 p1) const {
00993         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); }
00994         // Implicit conversion to "bool" using the safe_bool idiom
00995 private:
00996         typedef struct SafeBoolStruct {
00997                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
00998                 StaticFunctionPtr m_nonzero;
00999         } UselessTypedef;
01000     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01001 public:
01002         operator unspecified_bool_type() const {
01003         return empty()? 0: &SafeBoolStruct::m_nonzero;
01004     }
01005         // necessary to allow ==0 to work despite the safe_bool idiom
01006         inline bool operator==(StaticFunctionPtr funcptr) {
01007                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01008         inline bool operator!=(StaticFunctionPtr funcptr) { 
01009                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01010         inline bool operator ! () const {       // Is it bound to anything?
01011                         return !m_Closure; }
01012         inline bool empty() const       {
01013                         return !m_Closure; }
01014         void clear() { m_Closure.clear();}
01015         // Conversion to and from the DelegateMemento storage class
01016         const DelegateMemento & GetMemento() { return m_Closure; }
01017         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01018 
01019 private:        // Invoker for static functions
01020         RetType InvokeStaticFunction(Param1 p1) const {
01021         return (*(m_Closure.GetStaticFunction()))(p1); }
01022 };
01023 
01024 //N=2
01025 template<class Param1, class Param2, class RetType=detail::DefaultVoid>
01026 class FastDelegate2 {
01027 private:
01028         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01029         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
01030         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
01031         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
01032         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01033         ClosureType m_Closure;
01034 public:
01035         // Typedefs to aid generic programming
01036         typedef FastDelegate2 type;
01037 
01038         // Construction and comparison functions
01039         FastDelegate2() { clear(); }
01040         FastDelegate2(const FastDelegate2 &x) {
01041                 m_Closure.CopyFrom(this, x.m_Closure); }
01042         void operator = (const FastDelegate2 &x)  {
01043                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01048         bool operator <(const FastDelegate2 &x) const {
01049                 return m_Closure.IsLess(x.m_Closure);   }
01050         bool operator >(const FastDelegate2 &x) const {
01051                 return x.m_Closure.IsLess(m_Closure);   }
01052         // Binding to non-const member functions
01053         template < class X, class Y >
01054         FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) {
01055                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01056         template < class X, class Y >
01057         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) {
01058                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01059         // Binding to const member functions.
01060         template < class X, class Y >
01061         FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
01062                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01063         template < class X, class Y >
01064         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
01065                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01066         // Static functions. We convert them into a member function call.
01067         // This constructor also provides implicit conversion
01068         FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
01069                 bind(function_to_bind); }
01070         // for efficiency, prevent creation of a temporary
01071         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
01072                 bind(function_to_bind); }
01073         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) {
01074                 m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, 
01075                         function_to_bind); }
01076         // Invoke the delegate
01077         RetType operator() (Param1 p1, Param2 p2) const {
01078         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); }
01079         // Implicit conversion to "bool" using the safe_bool idiom
01080 private:
01081         typedef struct SafeBoolStruct {
01082                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01083                 StaticFunctionPtr m_nonzero;
01084         } UselessTypedef;
01085     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01086 public:
01087         operator unspecified_bool_type() const {
01088         return empty()? 0: &SafeBoolStruct::m_nonzero;
01089     }
01090         // necessary to allow ==0 to work despite the safe_bool idiom
01091         inline bool operator==(StaticFunctionPtr funcptr) {
01092                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01093         inline bool operator!=(StaticFunctionPtr funcptr) { 
01094                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01095         inline bool operator ! () const {       // Is it bound to anything?
01096                         return !m_Closure; }
01097         inline bool empty() const       {
01098                         return !m_Closure; }
01099         void clear() { m_Closure.clear();}
01100         // Conversion to and from the DelegateMemento storage class
01101         const DelegateMemento & GetMemento() { return m_Closure; }
01102         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01103 
01104 private:        // Invoker for static functions
01105         RetType InvokeStaticFunction(Param1 p1, Param2 p2) const {
01106         return (*(m_Closure.GetStaticFunction()))(p1, p2); }
01107 };
01108 
01109 //N=3
01110 template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
01111 class FastDelegate3 {
01112 private:
01113         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01114         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
01115         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
01116         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
01117         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01118         ClosureType m_Closure;
01119 public:
01120         // Typedefs to aid generic programming
01121         typedef FastDelegate3 type;
01122 
01123         // Construction and comparison functions
01124         FastDelegate3() { clear(); }
01125         FastDelegate3(const FastDelegate3 &x) {
01126                 m_Closure.CopyFrom(this, x.m_Closure); }
01127         void operator = (const FastDelegate3 &x)  {
01128                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01133         bool operator <(const FastDelegate3 &x) const {
01134                 return m_Closure.IsLess(x.m_Closure);   }
01135         bool operator >(const FastDelegate3 &x) const {
01136                 return x.m_Closure.IsLess(m_Closure);   }
01137         // Binding to non-const member functions
01138         template < class X, class Y >
01139         FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01140                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01141         template < class X, class Y >
01142         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
01143                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01144         // Binding to const member functions.
01145         template < class X, class Y >
01146         FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
01147                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01148         template < class X, class Y >
01149         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
01150                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01151         // Static functions. We convert them into a member function call.
01152         // This constructor also provides implicit conversion
01153         FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01154                 bind(function_to_bind); }
01155         // for efficiency, prevent creation of a temporary
01156         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01157                 bind(function_to_bind); }
01158         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
01159                 m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, 
01160                         function_to_bind); }
01161         // Invoke the delegate
01162         RetType operator() (Param1 p1, Param2 p2, Param3 p3) const {
01163         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); }
01164         // Implicit conversion to "bool" using the safe_bool idiom
01165 private:
01166         typedef struct SafeBoolStruct {
01167                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01168                 StaticFunctionPtr m_nonzero;
01169         } UselessTypedef;
01170     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01171 public:
01172         operator unspecified_bool_type() const {
01173         return empty()? 0: &SafeBoolStruct::m_nonzero;
01174     }
01175         // necessary to allow ==0 to work despite the safe_bool idiom
01176         inline bool operator==(StaticFunctionPtr funcptr) {
01177                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01178         inline bool operator!=(StaticFunctionPtr funcptr) { 
01179                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01180         inline bool operator ! () const {       // Is it bound to anything?
01181                         return !m_Closure; }
01182         inline bool empty() const       {
01183                         return !m_Closure; }
01184         void clear() { m_Closure.clear();}
01185         // Conversion to and from the DelegateMemento storage class
01186         const DelegateMemento & GetMemento() { return m_Closure; }
01187         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01188 
01189 private:        // Invoker for static functions
01190         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const {
01191         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); }
01192 };
01193 
01194 //N=4
01195 template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
01196 class FastDelegate4 {
01197 private:
01198         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01199         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01200         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01201         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01202         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01203         ClosureType m_Closure;
01204 public:
01205         // Typedefs to aid generic programming
01206         typedef FastDelegate4 type;
01207 
01208         // Construction and comparison functions
01209         FastDelegate4() { clear(); }
01210         FastDelegate4(const FastDelegate4 &x) {
01211                 m_Closure.CopyFrom(this, x.m_Closure); }
01212         void operator = (const FastDelegate4 &x)  {
01213                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01218         bool operator <(const FastDelegate4 &x) const {
01219                 return m_Closure.IsLess(x.m_Closure);   }
01220         bool operator >(const FastDelegate4 &x) const {
01221                 return x.m_Closure.IsLess(m_Closure);   }
01222         // Binding to non-const member functions
01223         template < class X, class Y >
01224         FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01225                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01226         template < class X, class Y >
01227         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
01228                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01229         // Binding to const member functions.
01230         template < class X, class Y >
01231         FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
01232                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01233         template < class X, class Y >
01234         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
01235                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01236         // Static functions. We convert them into a member function call.
01237         // This constructor also provides implicit conversion
01238         FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01239                 bind(function_to_bind); }
01240         // for efficiency, prevent creation of a temporary
01241         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01242                 bind(function_to_bind); }
01243         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
01244                 m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, 
01245                         function_to_bind); }
01246         // Invoke the delegate
01247         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
01248         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); }
01249         // Implicit conversion to "bool" using the safe_bool idiom
01250 private:
01251         typedef struct SafeBoolStruct {
01252                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01253                 StaticFunctionPtr m_nonzero;
01254         } UselessTypedef;
01255     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01256 public:
01257         operator unspecified_bool_type() const {
01258         return empty()? 0: &SafeBoolStruct::m_nonzero;
01259     }
01260         // necessary to allow ==0 to work despite the safe_bool idiom
01261         inline bool operator==(StaticFunctionPtr funcptr) {
01262                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01263         inline bool operator!=(StaticFunctionPtr funcptr) { 
01264                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01265         inline bool operator ! () const {       // Is it bound to anything?
01266                         return !m_Closure; }
01267         inline bool empty() const       {
01268                         return !m_Closure; }
01269         void clear() { m_Closure.clear();}
01270         // Conversion to and from the DelegateMemento storage class
01271         const DelegateMemento & GetMemento() { return m_Closure; }
01272         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01273 
01274 private:        // Invoker for static functions
01275         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
01276         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); }
01277 };
01278 
01279 //N=5
01280 template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
01281 class FastDelegate5 {
01282 private:
01283         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01284         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01285         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01286         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01287         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01288         ClosureType m_Closure;
01289 public:
01290         // Typedefs to aid generic programming
01291         typedef FastDelegate5 type;
01292 
01293         // Construction and comparison functions
01294         FastDelegate5() { clear(); }
01295         FastDelegate5(const FastDelegate5 &x) {
01296                 m_Closure.CopyFrom(this, x.m_Closure); }
01297         void operator = (const FastDelegate5 &x)  {
01298                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01303         bool operator <(const FastDelegate5 &x) const {
01304                 return m_Closure.IsLess(x.m_Closure);   }
01305         bool operator >(const FastDelegate5 &x) const {
01306                 return x.m_Closure.IsLess(m_Closure);   }
01307         // Binding to non-const member functions
01308         template < class X, class Y >
01309         FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01310                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01311         template < class X, class Y >
01312         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
01313                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01314         // Binding to const member functions.
01315         template < class X, class Y >
01316         FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
01317                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01318         template < class X, class Y >
01319         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
01320                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01321         // Static functions. We convert them into a member function call.
01322         // This constructor also provides implicit conversion
01323         FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01324                 bind(function_to_bind); }
01325         // for efficiency, prevent creation of a temporary
01326         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01327                 bind(function_to_bind); }
01328         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
01329                 m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, 
01330                         function_to_bind); }
01331         // Invoke the delegate
01332         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
01333         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); }
01334         // Implicit conversion to "bool" using the safe_bool idiom
01335 private:
01336         typedef struct SafeBoolStruct {
01337                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01338                 StaticFunctionPtr m_nonzero;
01339         } UselessTypedef;
01340     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01341 public:
01342         operator unspecified_bool_type() const {
01343         return empty()? 0: &SafeBoolStruct::m_nonzero;
01344     }
01345         // necessary to allow ==0 to work despite the safe_bool idiom
01346         inline bool operator==(StaticFunctionPtr funcptr) {
01347                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01348         inline bool operator!=(StaticFunctionPtr funcptr) { 
01349                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01350         inline bool operator ! () const {       // Is it bound to anything?
01351                         return !m_Closure; }
01352         inline bool empty() const       {
01353                         return !m_Closure; }
01354         void clear() { m_Closure.clear();}
01355         // Conversion to and from the DelegateMemento storage class
01356         const DelegateMemento & GetMemento() { return m_Closure; }
01357         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01358 
01359 private:        // Invoker for static functions
01360         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
01361         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); }
01362 };
01363 
01364 //N=6
01365 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
01366 class FastDelegate6 {
01367 private:
01368         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01369         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01370         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01371         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01372         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01373         ClosureType m_Closure;
01374 public:
01375         // Typedefs to aid generic programming
01376         typedef FastDelegate6 type;
01377 
01378         // Construction and comparison functions
01379         FastDelegate6() { clear(); }
01380         FastDelegate6(const FastDelegate6 &x) {
01381                 m_Closure.CopyFrom(this, x.m_Closure); }
01382         void operator = (const FastDelegate6 &x)  {
01383                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01388         bool operator <(const FastDelegate6 &x) const {
01389                 return m_Closure.IsLess(x.m_Closure);   }
01390         bool operator >(const FastDelegate6 &x) const {
01391                 return x.m_Closure.IsLess(m_Closure);   }
01392         // Binding to non-const member functions
01393         template < class X, class Y >
01394         FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01395                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01396         template < class X, class Y >
01397         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
01398                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01399         // Binding to const member functions.
01400         template < class X, class Y >
01401         FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
01402                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01403         template < class X, class Y >
01404         inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
01405                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01406         // Static functions. We convert them into a member function call.
01407         // This constructor also provides implicit conversion
01408         FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01409                 bind(function_to_bind); }
01410         // for efficiency, prevent creation of a temporary
01411         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01412                 bind(function_to_bind); }
01413         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
01414                 m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, 
01415                         function_to_bind); }
01416         // Invoke the delegate
01417         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
01418         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); }
01419         // Implicit conversion to "bool" using the safe_bool idiom
01420 private:
01421         typedef struct SafeBoolStruct {
01422                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01423                 StaticFunctionPtr m_nonzero;
01424         } UselessTypedef;
01425     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01426 public:
01427         operator unspecified_bool_type() const {
01428         return empty()? 0: &SafeBoolStruct::m_nonzero;
01429     }
01430         // necessary to allow ==0 to work despite the safe_bool idiom
01431         inline bool operator==(StaticFunctionPtr funcptr) {
01432                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01433         inline bool operator!=(StaticFunctionPtr funcptr) { 
01434                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01435         inline bool operator ! () const {       // Is it bound to anything?
01436                         return !m_Closure; }
01437         inline bool empty() const       {
01438                         return !m_Closure; }
01439         void clear() { m_Closure.clear();}
01440         // Conversion to and from the DelegateMemento storage class
01441         const DelegateMemento & GetMemento() { return m_Closure; }
01442         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01443 
01444 private:        // Invoker for static functions
01445         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
01446         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); }
01447 };
01448 
01449 //N=7
01450 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
01451 class FastDelegate7 {
01452 private:
01453         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01454         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01455         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01456         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01457         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01458         ClosureType m_Closure;
01459 public:
01460         // Typedefs to aid generic programming
01461         typedef FastDelegate7 type;
01462 
01463         // Construction and comparison functions
01464         FastDelegate7() { clear(); }
01465         FastDelegate7(const FastDelegate7 &x) {
01466                 m_Closure.CopyFrom(this, x.m_Closure); }
01467         void operator = (const FastDelegate7 &x)  {
01468                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01473         bool operator <(const FastDelegate7 &x) const {
01474                 return m_Closure.IsLess(x.m_Closure);   }
01475         bool operator >(const FastDelegate7 &x) const {
01476                 return x.m_Closure.IsLess(m_Closure);   }
01477         // Binding to non-const member functions
01478         template < class X, class Y >
01479         FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01480                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01481         template < class X, class Y >
01482         inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
01483                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01484         // Binding to const member functions.
01485         template < class X, class Y >
01486         FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
01487                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01488         template < class X, class Y >
01489         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) {
01490                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01491         // Static functions. We convert them into a member function call.
01492         // This constructor also provides implicit conversion
01493         FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01494                 bind(function_to_bind); }
01495         // for efficiency, prevent creation of a temporary
01496         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01497                 bind(function_to_bind); }
01498         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
01499                 m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, 
01500                         function_to_bind); }
01501         // Invoke the delegate
01502         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
01503         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); }
01504         // Implicit conversion to "bool" using the safe_bool idiom
01505 private:
01506         typedef struct SafeBoolStruct {
01507                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01508                 StaticFunctionPtr m_nonzero;
01509         } UselessTypedef;
01510     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01511 public:
01512         operator unspecified_bool_type() const {
01513         return empty()? 0: &SafeBoolStruct::m_nonzero;
01514     }
01515         // necessary to allow ==0 to work despite the safe_bool idiom
01516         inline bool operator==(StaticFunctionPtr funcptr) {
01517                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01518         inline bool operator!=(StaticFunctionPtr funcptr) { 
01519                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01520         inline bool operator ! () const {       // Is it bound to anything?
01521                         return !m_Closure; }
01522         inline bool empty() const       {
01523                         return !m_Closure; }
01524         void clear() { m_Closure.clear();}
01525         // Conversion to and from the DelegateMemento storage class
01526         const DelegateMemento & GetMemento() { return m_Closure; }
01527         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01528 
01529 private:        // Invoker for static functions
01530         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
01531         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); }
01532 };
01533 
01534 //N=8
01535 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
01536 class FastDelegate8 {
01537 private:
01538         typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
01539         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01540         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01541         typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01542         typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01543         ClosureType m_Closure;
01544 public:
01545         // Typedefs to aid generic programming
01546         typedef FastDelegate8 type;
01547 
01548         // Construction and comparison functions
01549         FastDelegate8() { clear(); }
01550         FastDelegate8(const FastDelegate8 &x) {
01551                 m_Closure.CopyFrom(this, x.m_Closure); }
01552         void operator = (const FastDelegate8 &x)  {
01553                 m_Closure.CopyFrom(this, 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.IsEqual(x.m_Closure); }
01558         bool operator <(const FastDelegate8 &x) const {
01559                 return m_Closure.IsLess(x.m_Closure);   }
01560         bool operator >(const FastDelegate8 &x) const {
01561                 return x.m_Closure.IsLess(m_Closure);   }
01562         // Binding to non-const member functions
01563         template < class X, class Y >
01564         FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01565                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
01566         template < class X, class Y >
01567         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)) {
01568                 m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);      }
01569         // Binding to const member functions.
01570         template < class X, class Y >
01571         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) {
01572                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);   }
01573         template < class X, class Y >
01574         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) {
01575                 m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);  }
01576         // Static functions. We convert them into a member function call.
01577         // This constructor also provides implicit conversion
01578         FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01579                 bind(function_to_bind); }
01580         // for efficiency, prevent creation of a temporary
01581         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01582                 bind(function_to_bind); }
01583         inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
01584                 m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, 
01585                         function_to_bind); }
01586         // Invoke the delegate
01587         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
01588         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); }
01589         // Implicit conversion to "bool" using the safe_bool idiom
01590 private:
01591         typedef struct SafeBoolStruct {
01592                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01593                 StaticFunctionPtr m_nonzero;
01594         } UselessTypedef;
01595     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01596 public:
01597         operator unspecified_bool_type() const {
01598         return empty()? 0: &SafeBoolStruct::m_nonzero;
01599     }
01600         // necessary to allow ==0 to work despite the safe_bool idiom
01601         inline bool operator==(StaticFunctionPtr funcptr) {
01602                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01603         inline bool operator!=(StaticFunctionPtr funcptr) { 
01604                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01605         inline bool operator ! () const {       // Is it bound to anything?
01606                         return !m_Closure; }
01607         inline bool empty() const       {
01608                         return !m_Closure; }
01609         void clear() { m_Closure.clear();}
01610         // Conversion to and from the DelegateMemento storage class
01611         const DelegateMemento & GetMemento() { return m_Closure; }
01612         void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01613 
01614 private:        // Invoker for static functions
01615         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
01616         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); }
01617 };
01618 
01619 
01621 //                                              Fast Delegates, part 4:
01622 // 
01623 //                              FastDelegate<> class (Original author: Jody Hagins)
01624 //      Allows boost::function style syntax like:
01625 //                      FastDelegate< double (int, long) >
01626 // instead of:
01627 //                      FastDelegate2< int, long, double >
01628 //
01630 
01631 #ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
01632 
01633 // Declare FastDelegate as a class template.  It will be specialized
01634 // later for all number of arguments.
01635 template <typename Signature>
01636 class FastDelegate;
01637 
01638 //N=0
01639 // Specialization to allow use of
01640 // FastDelegate< R (  ) >
01641 // instead of 
01642 // FastDelegate0 < R >
01643 template<typename R>
01644 class FastDelegate< R (  ) >
01645   // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
01646   : public FastDelegate0 < R >
01647 {
01648 public:
01649   // Make using the base type a bit easier via typedef.
01650   typedef FastDelegate0 < R > BaseType;
01651 
01652   // Allow users access to the specific type of this delegate.
01653   typedef FastDelegate SelfType;
01654 
01655   // Mimic the base class constructors.
01656   FastDelegate() : BaseType() { }
01657 
01658   template < class X, class Y >
01659   FastDelegate(Y * pthis, 
01660     R (X::* function_to_bind)(  ))
01661     : BaseType(pthis, function_to_bind)  { }
01662 
01663   template < class X, class Y >
01664   FastDelegate(const Y *pthis,
01665       R (X::* function_to_bind)(  ) const)
01666     : BaseType(pthis, function_to_bind)
01667   {  }
01668 
01669   FastDelegate(R (*function_to_bind)(  ))
01670     : BaseType(function_to_bind)  { }
01671   void operator = (const BaseType &x)  {          
01672                 *static_cast<BaseType*>(this) = x; }
01673 };
01674 
01675 //N=1
01676 // Specialization to allow use of
01677 // FastDelegate< R ( Param1 ) >
01678 // instead of 
01679 // FastDelegate1 < Param1, R >
01680 template<typename R, class Param1>
01681 class FastDelegate< R ( Param1 ) >
01682   // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
01683   : public FastDelegate1 < Param1, R >
01684 {
01685 public:
01686   // Make using the base type a bit easier via typedef.
01687   typedef FastDelegate1 < Param1, R > BaseType;
01688 
01689   // Allow users access to the specific type of this delegate.
01690   typedef FastDelegate SelfType;
01691 
01692   // Mimic the base class constructors.
01693   FastDelegate() : BaseType() { }
01694 
01695   template < class X, class Y >
01696   FastDelegate(Y * pthis, 
01697     R (X::* function_to_bind)( Param1 p1 ))
01698     : BaseType(pthis, function_to_bind)  { }
01699 
01700   template < class X, class Y >
01701   FastDelegate(const Y *pthis,
01702       R (X::* function_to_bind)( Param1 p1 ) const)
01703     : BaseType(pthis, function_to_bind)
01704   {  }
01705 
01706   FastDelegate(R (*function_to_bind)( Param1 p1 ))
01707     : BaseType(function_to_bind)  { }
01708   void operator = (const BaseType &x)  {          
01709                 *static_cast<BaseType*>(this) = x; }
01710 };
01711 
01712 //N=2
01713 // Specialization to allow use of
01714 // FastDelegate< R ( Param1, Param2 ) >
01715 // instead of 
01716 // FastDelegate2 < Param1, Param2, R >
01717 template<typename R, class Param1, class Param2>
01718 class FastDelegate< R ( Param1, Param2 ) >
01719   // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
01720   : public FastDelegate2 < Param1, Param2, R >
01721 {
01722 public:
01723   // Make using the base type a bit easier via typedef.
01724   typedef FastDelegate2 < Param1, Param2, R > BaseType;
01725 
01726   // Allow users access to the specific type of this delegate.
01727   typedef FastDelegate SelfType;
01728 
01729   // Mimic the base class constructors.
01730   FastDelegate() : BaseType() { }
01731 
01732   template < class X, class Y >
01733   FastDelegate(Y * pthis, 
01734     R (X::* function_to_bind)( Param1 p1, Param2 p2 ))
01735     : BaseType(pthis, function_to_bind)  { }
01736 
01737   template < class X, class Y >
01738   FastDelegate(const Y *pthis,
01739       R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const)
01740     : BaseType(pthis, function_to_bind)
01741   {  }
01742 
01743   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 ))
01744     : BaseType(function_to_bind)  { }
01745   void operator = (const BaseType &x)  {          
01746                 *static_cast<BaseType*>(this) = x; }
01747 };
01748 
01749 //N=3
01750 // Specialization to allow use of
01751 // FastDelegate< R ( Param1, Param2, Param3 ) >
01752 // instead of 
01753 // FastDelegate3 < Param1, Param2, Param3, R >
01754 template<typename R, class Param1, class Param2, class Param3>
01755 class FastDelegate< R ( Param1, Param2, Param3 ) >
01756   // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
01757   : public FastDelegate3 < Param1, Param2, Param3, R >
01758 {
01759 public:
01760   // Make using the base type a bit easier via typedef.
01761   typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType;
01762 
01763   // Allow users access to the specific type of this delegate.
01764   typedef FastDelegate SelfType;
01765 
01766   // Mimic the base class constructors.
01767   FastDelegate() : BaseType() { }
01768 
01769   template < class X, class Y >
01770   FastDelegate(Y * pthis, 
01771     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
01772     : BaseType(pthis, function_to_bind)  { }
01773 
01774   template < class X, class Y >
01775   FastDelegate(const Y *pthis,
01776       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const)
01777     : BaseType(pthis, function_to_bind)
01778   {  }
01779 
01780   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
01781     : BaseType(function_to_bind)  { }
01782   void operator = (const BaseType &x)  {          
01783                 *static_cast<BaseType*>(this) = x; }
01784 };
01785 
01786 //N=4
01787 // Specialization to allow use of
01788 // FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
01789 // instead of 
01790 // FastDelegate4 < Param1, Param2, Param3, Param4, R >
01791 template<typename R, class Param1, class Param2, class Param3, class Param4>
01792 class FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
01793   // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
01794   : public FastDelegate4 < Param1, Param2, Param3, Param4, R >
01795 {
01796 public:
01797   // Make using the base type a bit easier via typedef.
01798   typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType;
01799 
01800   // Allow users access to the specific type of this delegate.
01801   typedef FastDelegate SelfType;
01802 
01803   // Mimic the base class constructors.
01804   FastDelegate() : BaseType() { }
01805 
01806   template < class X, class Y >
01807   FastDelegate(Y * pthis, 
01808     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
01809     : BaseType(pthis, function_to_bind)  { }
01810 
01811   template < class X, class Y >
01812   FastDelegate(const Y *pthis,
01813       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const)
01814     : BaseType(pthis, function_to_bind)
01815   {  }
01816 
01817   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
01818     : BaseType(function_to_bind)  { }
01819   void operator = (const BaseType &x)  {          
01820                 *static_cast<BaseType*>(this) = x; }
01821 };
01822 
01823 //N=5
01824 // Specialization to allow use of
01825 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
01826 // instead of 
01827 // FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
01828 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
01829 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
01830   // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
01831   : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
01832 {
01833 public:
01834   // Make using the base type a bit easier via typedef.
01835   typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType;
01836 
01837   // Allow users access to the specific type of this delegate.
01838   typedef FastDelegate SelfType;
01839 
01840   // Mimic the base class constructors.
01841   FastDelegate() : BaseType() { }
01842 
01843   template < class X, class Y >
01844   FastDelegate(Y * pthis, 
01845     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
01846     : BaseType(pthis, function_to_bind)  { }
01847 
01848   template < class X, class Y >
01849   FastDelegate(const Y *pthis,
01850       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const)
01851     : BaseType(pthis, function_to_bind)
01852   {  }
01853 
01854   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
01855     : BaseType(function_to_bind)  { }
01856   void operator = (const BaseType &x)  {          
01857                 *static_cast<BaseType*>(this) = x; }
01858 };
01859 
01860 //N=6
01861 // Specialization to allow use of
01862 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
01863 // instead of 
01864 // FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
01865 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
01866 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
01867   // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
01868   : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
01869 {
01870 public:
01871   // Make using the base type a bit easier via typedef.
01872   typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType;
01873 
01874   // Allow users access to the specific type of this delegate.
01875   typedef FastDelegate SelfType;
01876 
01877   // Mimic the base class constructors.
01878   FastDelegate() : BaseType() { }
01879 
01880   template < class X, class Y >
01881   FastDelegate(Y * pthis, 
01882     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
01883     : BaseType(pthis, function_to_bind)  { }
01884 
01885   template < class X, class Y >
01886   FastDelegate(const Y *pthis,
01887       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const)
01888     : BaseType(pthis, function_to_bind)
01889   {  }
01890 
01891   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
01892     : BaseType(function_to_bind)  { }
01893   void operator = (const BaseType &x)  {          
01894                 *static_cast<BaseType*>(this) = x; }
01895 };
01896 
01897 //N=7
01898 // Specialization to allow use of
01899 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
01900 // instead of 
01901 // FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
01902 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
01903 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
01904   // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
01905   : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
01906 {
01907 public:
01908   // Make using the base type a bit easier via typedef.
01909   typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType;
01910 
01911   // Allow users access to the specific type of this delegate.
01912   typedef FastDelegate SelfType;
01913 
01914   // Mimic the base class constructors.
01915   FastDelegate() : BaseType() { }
01916 
01917   template < class X, class Y >
01918   FastDelegate(Y * pthis, 
01919     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
01920     : BaseType(pthis, function_to_bind)  { }
01921 
01922   template < class X, class Y >
01923   FastDelegate(const Y *pthis,
01924       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const)
01925     : BaseType(pthis, function_to_bind)
01926   {  }
01927 
01928   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
01929     : BaseType(function_to_bind)  { }
01930   void operator = (const BaseType &x)  {          
01931                 *static_cast<BaseType*>(this) = x; }
01932 };
01933 
01934 //N=8
01935 // Specialization to allow use of
01936 // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
01937 // instead of 
01938 // FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
01939 template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
01940 class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
01941   // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
01942   : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
01943 {
01944 public:
01945   // Make using the base type a bit easier via typedef.
01946   typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType;
01947 
01948   // Allow users access to the specific type of this delegate.
01949   typedef FastDelegate SelfType;
01950 
01951   // Mimic the base class constructors.
01952   FastDelegate() : BaseType() { }
01953 
01954   template < class X, class Y >
01955   FastDelegate(Y * pthis, 
01956     R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
01957     : BaseType(pthis, function_to_bind)  { }
01958 
01959   template < class X, class Y >
01960   FastDelegate(const Y *pthis,
01961       R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const)
01962     : BaseType(pthis, function_to_bind)
01963   {  }
01964 
01965   FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
01966     : BaseType(function_to_bind)  { }
01967   void operator = (const BaseType &x)  {          
01968                 *static_cast<BaseType*>(this) = x; }
01969 };
01970 
01971 
01972 #endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
01973 
01975 //                                              Fast Delegates, part 5:
01976 //
01977 //                              MakeDelegate() helper function
01978 //
01979 //                      MakeDelegate(&x, &X::func) returns a fastdelegate of the type
01980 //                      necessary for calling x.func() with the correct number of arguments.
01981 //                      This makes it possible to eliminate many typedefs from user code.
01982 //
01984 
01985 // Also declare overloads of a MakeDelegate() global function to 
01986 // reduce the need for typedefs.
01987 // We need seperate overloads for const and non-const member functions.
01988 // Also, because of the weird rule about the class of derived member function pointers,
01989 // implicit downcasts may need to be applied later to the 'this' pointer.
01990 // That's why two classes (X and Y) appear in the definitions. Y must be implicitly
01991 // castable to X.
01992 
01993 // Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
01994 // GCC 3.2 and later won't compile this unless it's preceded by 'typename',
01995 // but VC6 doesn't allow 'typename' in this context.
01996 // So, I have to use a macro.
01997 
01998 #ifdef FASTDLGT_VC6
01999 #define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
02000 #else 
02001 #define FASTDLGT_RETTYPE RetType
02002 #endif
02003 
02004 //N=0
02005 template <class X, class Y, class RetType>
02006 FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)()) { 
02007         return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
02008 }
02009 
02010 template <class X, class Y, class RetType>
02011 FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)() const) { 
02012         return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
02013 }
02014 
02015 //N=1
02016 template <class X, class Y, class Param1, class RetType>
02017 FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { 
02018         return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
02019 }
02020 
02021 template <class X, class Y, class Param1, class RetType>
02022 FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { 
02023         return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
02024 }
02025 
02026 //N=2
02027 template <class X, class Y, class Param1, class Param2, class RetType>
02028 FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { 
02029         return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
02030 }
02031 
02032 template <class X, class Y, class Param1, class Param2, class RetType>
02033 FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { 
02034         return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
02035 }
02036 
02037 //N=3
02038 template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
02039 FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { 
02040         return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
02041 }
02042 
02043 template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
02044 FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { 
02045         return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
02046 }
02047 
02048 //N=4
02049 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
02050 FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { 
02051         return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
02052 }
02053 
02054 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
02055 FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { 
02056         return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
02057 }
02058 
02059 //N=5
02060 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
02061 FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { 
02062         return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
02063 }
02064 
02065 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
02066 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) { 
02067         return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
02068 }
02069 
02070 //N=6
02071 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
02072 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)) { 
02073         return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
02074 }
02075 
02076 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
02077 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) { 
02078         return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
02079 }
02080 
02081 //N=7
02082 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
02083 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)) { 
02084         return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
02085 }
02086 
02087 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
02088 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) { 
02089         return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
02090 }
02091 
02092 //N=8
02093 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
02094 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)) { 
02095         return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
02096 }
02097 
02098 template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
02099 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) { 
02100         return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
02101 }
02102 
02103 
02104  // clean up after ourselves...
02105 #undef FASTDLGT_RETTYPE
02106 
02107 } // namespace fastdelegate
02108 
02109 #endif // !defined(FASTDELEGATE_H)
02110