FastDelegate.h

Engine/source/core/util/FastDelegate.h

More...

Classes:

Namespaces:

Public Defines

Detailed Description

Public Defines

FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX() 
FASTDELEGATE_USESTATICFUNCTIONHACK() 
FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME;
FASTDLGT_RETTYPE() RetType
   1
   2//                FastDelegate.h 
   3// Efficient delegates in C++ that generate only two lines of asm code!
   4//  Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
   5//
   6//                - Don Clugston, Mar 2004.
   7//    Major contributions were made by Jody Hagins.
   8// History:
   9// 24-Apr-04 1.0  * Submitted to CodeProject. 
  10// 28-Apr-04 1.1  * Prevent most unsafe uses of evil static function hack.
  11//            * Improved syntax for horrible_cast (thanks Paul Bludov).
  12//            * Tested on Metrowerks MWCC and Intel ICL (IA32)
  13//            * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
  14// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
  15//            * Now works on /clr "managed C++" code on VC7, VC7.1
  16//            * Comeau C++ now compiles without warnings.
  17//            * Prevent the virtual inheritance case from being used on 
  18//               VC6 and earlier, which generate incorrect code.
  19//            * Improved warning and error messages. Non-standard hacks
  20//              now have compile-time checks to make them safer.
  21//            * implicit_cast used instead of static_cast in many cases.
  22//            * If calling a const member function, a const class pointer can be used.
  23//            * MakeDelegate() global helper function added to simplify pass-by-value.
  24//            * Added fastdelegate.clear()
  25// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)
  26// 30-Oct-04 1.3  * Support for (non-void) return values.
  27//            * No more workarounds in client code!
  28//              MSVC and Intel now use a clever hack invented by John Dlugosz:
  29//               - The FASTDELEGATEDECLARE workaround is no longer necessary.
  30//              - No more warning messages for VC6
  31//            * Less use of macros. Error messages should be more comprehensible.
  32//            * Added include guards
  33//            * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks).
  34//            * Now tested on VS 2005 Express Beta, PGI C++
  35// 24-Dec-04 1.4  * Added DelegateMemento, to allow collections of disparate delegates.
  36//                * <,>,<=,>= comparison operators to allow storage in ordered containers.
  37//            * Substantial reduction of code size, especially the 'Closure' class.
  38//            * Standardised all the compiler-specific workarounds.
  39//                * MFP conversion now works for CodePlay (but not yet supported in the full code).
  40//                * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
  41//            * New syntax: FastDelegate< int (char *, double) >. 
  42// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric).
  43//            * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.
  44// 30-Mar-05 1.5  * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())"
  45//            * Fully supported by CodePlay VectorC
  46//                * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC!
  47//                * More optimal assignment,== and != operators for static function pointers.
  48
  49#ifndef FASTDELEGATE_H
  50#define FASTDELEGATE_H
  51#if defined(_MSC_VER) && (_MSC_VER > 1000)
  52#pragma once
  53#endif // defined(_MSC_VER) && (_MSC_VER > 1000)
  54
  55////////////////////////////////////////////////////////////////////////////////
  56//                Configuration options
  57//
  58////////////////////////////////////////////////////////////////////////////////
  59
  60// Uncomment the following #define for optimally-sized delegates.
  61// In this case, the generated asm code is almost identical to the code you'd get
  62// if the compiler had native support for delegates.
  63// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). 
  64// Thus, it will not work for DOS compilers using the medium model.
  65// It will also probably fail on some DSP systems.
  66#define FASTDELEGATE_USESTATICFUNCTIONHACK
  67
  68// Uncomment the next line to allow function declarator syntax.
  69// It is automatically enabled for those compilers where it is known to work.
  70#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
  71
  72////////////////////////////////////////////////////////////////////////////////
  73//                Compiler identification for workarounds
  74//
  75////////////////////////////////////////////////////////////////////////////////
  76
  77// Compiler identification. It's not easy to identify Visual C++ because
  78// many vendors fraudulently define Microsoft's identifiers.
  79#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)
  80#define FASTDLGT_ISMSVC
  81
  82#if (_MSC_VER <1300) // Many workarounds are required for VC6.
  83#define FASTDLGT_VC6
  84#pragma warning(disable:4786) // disable this ridiculous warning
  85#endif
  86
  87#endif
  88
  89// Does the compiler uses Microsoft's member function pointer structure?
  90// If so, it needs special treatment.
  91// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's 
  92// identifier, _MSC_VER. We need to filter Metrowerks out.
  93#if defined(_MSC_VER) && !defined(__MWERKS__)
  94#define FASTDLGT_MICROSOFT_MFP
  95
  96#if !defined(__VECTOR_C)
  97// CodePlay doesn't have the __single/multi/virtual_inheritance keywords
  98#define FASTDLGT_HASINHERITANCE_KEYWORDS
  99#endif
 100#endif
 101
 102// Does it allow function declarator syntax? The following compilers are known to work:
 103#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1
 104#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
 105#endif
 106
 107// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.
 108#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)
 109#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
 110#endif
 111
 112// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
 113#if defined (__MWERKS__)
 114#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
 115#endif
 116
 117#ifdef __GNUC__ // Workaround GCC bug #8271 
 118   // At present, GCC doesn't recognize constness of MFPs in templates
 119#define FASTDELEGATE_GCC_BUG_8271
 120#endif
 121
 122
 123
 124////////////////////////////////////////////////////////////////////////////////
 125//                General tricks used in this code
 126//
 127// (a) Error messages are generated by typdefing an array of negative size to
 128//     generate compile-time errors.
 129// (b) Warning messages on MSVC are generated by declaring unused variables, and
 130//     enabling the "variable XXX is never used" warning.
 131// (c) Unions are used in a few compiler-specific cases to perform illegal casts.
 132// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
 133//     (char *) first to ensure that the correct number of *bytes* are added.
 134//
 135////////////////////////////////////////////////////////////////////////////////
 136//                Helper templates
 137//
 138////////////////////////////////////////////////////////////////////////////////
 139
 140
 141namespace fastdelegate {
 142namespace detail {   // we'll hide the implementation details in a nested namespace.
 143
 144//    implicit_cast< >
 145// I believe this was originally going to be in the C++ standard but 
 146// was left out by accident. It's even milder than static_cast.
 147// I use it instead of static_cast<> to emphasize that I'm not doing
 148// anything nasty. 
 149// Usage is identical to static_cast<>
 150template <class OutputClass, class InputClass>
 151inline OutputClass implicit_cast(InputClass input){
 152   return input;
 153}
 154
 155//    horrible_cast< >
 156// This is truly evil. It completely subverts C++'s type system, allowing you 
 157// to cast from any class to any other class. Technically, using a union 
 158// to perform the cast is undefined behaviour (even in C). But we can see if
 159// it is OK by checking that the union is the same size as each of its members.
 160// horrible_cast<> should only be used for compiler-specific workarounds. 
 161// Usage is identical to reinterpret_cast<>.
 162
 163// This union is declared outside the horrible_cast because BCC 5.5.1
 164// can't inline a function with a nested class, and gives a warning.
 165template <class OutputClass, class InputClass>
 166union horrible_union{
 167   OutputClass out;
 168   InputClass in;
 169};
 170
 171template <class OutputClass, class InputClass>
 172inline OutputClass horrible_cast(const InputClass input){
 173   horrible_union<OutputClass, InputClass> u;
 174   // Cause a compile-time error if in, out and u are not the same size.
 175   // If the compile fails here, it means the compiler has peculiar
 176   // unions which would prevent the cast from working.
 177   typedef S32 ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) 
 178      && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
 179   u.in = input;
 180   return u.out;
 181}
 182
 183////////////////////////////////////////////////////////////////////////////////
 184//                Workarounds
 185//
 186////////////////////////////////////////////////////////////////////////////////
 187
 188// Backwards compatibility: This macro used to be necessary in the virtual inheritance
 189// case for Intel and Microsoft. Now it just forward-declares the class.
 190#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME;
 191
 192// Prevent use of the static function hack with the DOS medium model.
 193#ifdef __MEDIUM__
 194#undef FASTDELEGATE_USESTATICFUNCTIONHACK
 195#endif
 196
 197//       DefaultVoid - a workaround for 'void' templates in VC6.
 198//
 199//  (1) VC6 and earlier do not allow 'void' as a default template argument.
 200//  (2) They also doesn't allow you to return 'void' from a function.
 201//
 202// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use
 203//   when we'd like to use 'void'. We convert it into 'void' and back
 204//   using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
 205// Workaround for (2): On VC6, the code for calling a void function is
 206//   identical to the code for calling a non-void function in which the
 207//   return value is never used, provided the return value is returned
 208//   in the EAX register, rather than on the stack. 
 209//   This is true for most fundamental types such as int, enum, void *.
 210//   Const void * is the safest option since it doesn't participate 
 211//   in any automatic conversions. But on a 16-bit compiler it might
 212//   cause extra code to be generated, so we disable it for all compilers
 213//   except for VC6 (and VC5).
 214#ifdef FASTDLGT_VC6
 215// VC6 workaround
 216typedef const void * DefaultVoid;
 217#else
 218// On any other compiler, just use a normal void.
 219typedef void DefaultVoid;
 220#endif
 221
 222// Translate from 'DefaultVoid' to 'void'.
 223// Everything else is unchanged
 224template <class T>
 225struct DefaultVoidToVoid { typedef T type; };
 226
 227template <>
 228struct DefaultVoidToVoid<DefaultVoid> {   typedef void type; };
 229
 230// Translate from 'void' into 'DefaultVoid'
 231// Everything else is unchanged
 232template <class T>
 233struct VoidToDefaultVoid { typedef T type; };
 234
 235template <>
 236struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
 237
 238
 239
 240////////////////////////////////////////////////////////////////////////////////
 241//                Fast Delegates, part 1:
 242//
 243//    Conversion of member function pointer to a standard form
 244//
 245////////////////////////////////////////////////////////////////////////////////
 246
 247// GenericClass is a fake class, ONLY used to provide a type.
 248// It is vitally important that it is never defined, so that the compiler doesn't
 249// think it can optimize the invocation. For example, Borland generates simpler
 250// code if it knows the class only uses single inheritance.
 251
 252// Compilers using Microsoft's structure need to be treated as a special case.
 253#ifdef  FASTDLGT_MICROSOFT_MFP
 254
 255#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
 256   // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP 
 257   // (4 bytes), even when the /vmg option is used. Declaring an empty class 
 258   // would give 16 byte pointers in this case....
 259   class __single_inheritance GenericClass;
 260#endif
 261   // ...but for Codeplay, an empty class *always* gives 4 byte pointers.
 262   // If compiled with the /clr option ("managed C++"), the JIT compiler thinks
 263   // it needs to load GenericClass before it can call any of its functions,
 264   // (compiles OK but crashes at runtime!), so we need to declare an 
 265   // empty class to make it happy.
 266   // Codeplay and VC4 can't cope with the unknown_inheritance case either.
 267   class GenericClass {};
 268#else
 269   class GenericClass;
 270#endif
 271
 272// The size of a single inheritance member function pointer.
 273const S32 SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());
 274
 275//                SimplifyMemFunc< >::Convert()
 276//
 277// A template function that converts an arbitrary member function pointer into the 
 278// simplest possible form of member function pointer, using a supplied 'this' pointer.
 279//  According to the standard, this can be done legally with reinterpret_cast<>.
 280// For (non-standard) compilers which use member function pointers which vary in size 
 281//  depending on the class, we need to use   knowledge of the internal structure of a 
 282//  member function pointer, as used by the compiler. Template specialization is used
 283//  to distinguish between the sizes. Because some compilers don't support partial 
 284// template specialisation, I use full specialisation of a wrapper struct.
 285
 286// general case -- don't know how to convert it. Force a compile failure
 287template <S32 N>
 288struct SimplifyMemFunc {
 289   template <class X, class XFuncType, class GenericMemFuncType>
 290   inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
 291      GenericMemFuncType &bound_func) { 
 292      // Unsupported member function type -- force a compile failure.
 293       // (it's illegal to have a array with negative size).
 294      typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
 295      return 0; 
 296   }
 297};
 298
 299// For compilers where all member func ptrs are the same size, everything goes here.
 300// For non-standard compilers, only single_inheritance classes go here.
 301template <>
 302struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE>  {  
 303   template <class X, class XFuncType, class GenericMemFuncType>
 304   inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
 305         GenericMemFuncType &bound_func) {
 306#if defined __DMC__  
 307      // Digital Mars doesn't allow you to cast between abitrary PMF's, 
 308      // even though the standard says you can. The 32-bit compiler lets you
 309      // static_cast through an int, but the DOS compiler doesn't.
 310      bound_func = horrible_cast<GenericMemFuncType>(function_to_bind);
 311#else 
 312        bound_func = reinterpret_cast<GenericMemFuncType>(function_to_bind);
 313#endif
 314        return reinterpret_cast<GenericClass *>(pthis);
 315   }
 316};
 317
 318////////////////////////////////////////////////////////////////////////////////
 319//                Fast Delegates, part 1b:
 320//
 321//             Workarounds for Microsoft and Intel
 322//
 323////////////////////////////////////////////////////////////////////////////////
 324
 325
 326// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
 327// need to be treated as a special case.
 328#ifdef FASTDLGT_MICROSOFT_MFP
 329
 330// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
 331// at the start of each function for extra safety, but VC6 seems to ICE
 332// intermittently if you do this inside a template.
 333
 334// __multiple_inheritance classes go here
 335// Nasty hack for Microsoft and Intel (IA32 and Itanium)
 336template<>
 337struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) >  {
 338   template <class X, class XFuncType, class GenericMemFuncType>
 339   inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
 340      GenericMemFuncType &bound_func) { 
 341      // We need to use a horrible_cast to do this conversion.
 342      // In MSVC, a multiple inheritance member pointer is internally defined as:
 343        union {
 344         XFuncType func;
 345         struct {  
 346            GenericMemFuncType funcaddress; // points to the actual member function
 347            S32 delta;       // #BYTES to be added to the 'this' pointer
 348         }s;
 349        } u;
 350      // Check that the horrible_cast will work
 351      typedef S32 ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1];
 352        u.func = function_to_bind;
 353      bound_func = u.s.funcaddress;
 354      return reinterpret_cast<GenericClass *>(reinterpret_cast<char *>(pthis) + u.s.delta); 
 355   }
 356};
 357
 358// virtual inheritance is a real nuisance. It's inefficient and complicated.
 359// On MSVC and Intel, there isn't enough information in the pointer itself to
 360// enable conversion to a closure pointer. Earlier versions of this code didn't
 361// work for all cases, and generated a compile-time error instead.
 362// But a very clever hack invented by John M. Dlugosz solves this problem.
 363// My code is somewhat different to his: I have no asm code, and I make no 
 364// assumptions about the calling convention that is used.
 365
 366// In VC++ and ICL, a virtual_inheritance member pointer 
 367// is internally defined as:
 368struct MicrosoftVirtualMFP {
 369   void (GenericClass::*codeptr)(); // points to the actual member function
 370   S32 delta;     // #bytes to be added to the 'this' pointer
 371   S32 vtable_index; // or 0 if no virtual inheritance
 372};
 373// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
 374// m_codeptr member is *always* called, regardless of the values of the other
 375// members. (This is *not* true for other compilers, eg GCC, which obtain the
 376// function address from the vtable if a virtual function is being called).
 377// Dlugosz's trick is to make the codeptr point to a probe function which
 378// returns the 'this' pointer that was used.
 379
 380// Define a generic class that uses virtual inheritance.
 381// It has a trival member function that returns the value of the 'this' pointer.
 382struct GenericVirtualClass : virtual public GenericClass
 383{
 384   typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
 385   GenericVirtualClass * GetThis() { return this; }
 386};
 387
 388// __virtual_inheritance classes go here
 389template <>
 390struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 2*sizeof(int) >
 391{
 392
 393   template <class X, class XFuncType, class GenericMemFuncType>
 394   inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
 395      GenericMemFuncType &bound_func) {
 396      union {
 397         XFuncType func;
 398         GenericClass* (X::*ProbeFunc)();
 399         MicrosoftVirtualMFP s;
 400      } u;
 401      u.func = function_to_bind;
 402      bound_func = reinterpret_cast<GenericMemFuncType>(u.s.codeptr);
 403      union {
 404         GenericVirtualClass::ProbePtrType virtfunc;
 405         MicrosoftVirtualMFP s;
 406      } u2;
 407      // Check that the horrible_cast<>s will work
 408      typedef S32 ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)
 409         && sizeof(function_to_bind)==sizeof(u.ProbeFunc)
 410         && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
 411   // Unfortunately, taking the address of a MF prevents it from being inlined, so 
 412   // this next line can't be completely optimised away by the compiler.
 413      u2.virtfunc = &GenericVirtualClass::GetThis;
 414      u.s.codeptr = u2.s.codeptr;
 415      return (pthis->*u.ProbeFunc)();
 416   }
 417};
 418
 419#if (_MSC_VER <1300)
 420
 421// Nasty hack for Microsoft Visual C++ 6.0
 422// unknown_inheritance classes go here
 423// There is a compiler bug in MSVC6 which generates incorrect code in this case!!
 424template <>
 425struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
 426{
 427   template <class X, class XFuncType, class GenericMemFuncType>
 428   inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
 429      GenericMemFuncType &bound_func) {
 430      // There is an apalling but obscure compiler bug in MSVC6 and earlier:
 431      // vtable_index and 'vtordisp' are always set to 0 in the 
 432      // unknown_inheritance case!
 433      // This means that an incorrect function could be called!!!
 434      // Compiling with the /vmg option leads to potentially incorrect code.
 435      // This is probably the reason that the IDE has a user interface for specifying
 436      // the /vmg option, but it is disabled -  you can only specify /vmg on 
 437      // the command line. In VC1.5 and earlier, the compiler would ICE if it ever
 438      // encountered this situation.
 439      // It is OK to use the /vmg option if /vmm or /vms is specified.
 440
 441      // Fortunately, the wrong function is only called in very obscure cases.
 442      // It only occurs when a derived class overrides a virtual function declared 
 443      // in a virtual base class, and the member function 
 444      // points to the *Derived* version of that function. The problem can be
 445      // completely averted in 100% of cases by using the *Base class* for the 
 446      // member fpointer. Ie, if you use the base class as an interface, you'll
 447      // stay out of trouble.
 448      // Occasionally, you might want to point directly to a derived class function
 449      // that isn't an override of a base class. In this case, both vtable_index 
 450      // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
 451      // We can generate correct code in this case. To prevent an incorrect call from
 452      // ever being made, on MSVC6 we generate a warning, and call a function to 
 453      // make the program crash instantly. 
 454      typedef char ERROR_VC6CompilerBug[-100];
 455      return 0; 
 456   }
 457};
 458
 459
 460#else 
 461
 462// Nasty hack for Microsoft and Intel (IA32 and Itanium)
 463// unknown_inheritance classes go here 
 464// This is probably the ugliest bit of code I've ever written. Look at the casts!
 465// There is a compiler bug in MSVC6 which prevents it from using this code.
 466template <>
 467struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
 468{
 469   template <class X, class XFuncType, class GenericMemFuncType>
 470   inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
 471         GenericMemFuncType &bound_func) {
 472      // The member function pointer is 16 bytes long. We can't use a normal cast, but
 473      // we can use a union to do the conversion.
 474      union {
 475         XFuncType func;
 476         // In VC++ and ICL, an unknown_inheritance member pointer 
 477         // is internally defined as:
 478         struct {
 479            GenericMemFuncType m_funcaddress; // points to the actual member function
 480            S32 delta;     // #bytes to be added to the 'this' pointer
 481            S32 vtordisp;     // #bytes to add to 'this' to find the vtable
 482            S32 vtable_index; // or 0 if no virtual inheritance
 483         } s;
 484      } u;
 485      // Check that the horrible_cast will work
 486      typedef S32 ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1];
 487      u.func = function_to_bind;
 488      bound_func = u.s.funcaddress;
 489      S32 virtual_delta = 0;
 490      if (u.s.vtable_index) { // Virtual inheritance is used
 491         // First, get to the vtable. 
 492         // It is 'vtordisp' bytes from the start of the class.
 493         const S32 * vtable = *reinterpret_cast<const S32 *const*>(
 494            reinterpret_cast<const char *>(pthis) + u.s.vtordisp );
 495
 496         // 'vtable_index' tells us where in the table we should be looking.
 497         virtual_delta = u.s.vtordisp + *reinterpret_cast<const S32 *>( 
 498            reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
 499      }
 500      // The int at 'virtual_delta' gives us the amount to add to 'this'.
 501        // Finally we can add the three components together. Phew!
 502        return reinterpret_cast<GenericClass *>(
 503         reinterpret_cast<char *>(pthis) + u.s.delta + virtual_delta);
 504   };
 505};
 506#endif // MSVC 7 and greater
 507
 508#endif // MS/Intel hacks
 509
 510}  // namespace detail
 511
 512////////////////////////////////////////////////////////////////////////////////
 513//                Fast Delegates, part 2:
 514//
 515// Define the delegate storage, and cope with static functions
 516//
 517////////////////////////////////////////////////////////////////////////////////
 518
 519// DelegateMemento -- an opaque structure which can hold an arbitary delegate.
 520// It knows nothing about the calling convention or number of arguments used by
 521// the function pointed to.
 522// It supplies comparison operators so that it can be stored in STL collections.
 523// It cannot be set to anything other than null, nor invoked directly: 
 524//   it must be converted to a specific delegate.
 525
 526// Implementation:
 527// There are two possible implementations: the Safe method and the Evil method.
 528//          DelegateMemento - Safe version
 529//
 530// This implementation is standard-compliant, but a bit tricky.
 531// A static function pointer is stored inside the class. 
 532// Here are the valid values:
 533// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
 534// |   0          |  0       |   0        | Empty          |
 535// |   !=0              |(dontcare)|  Invoker   | Static function|
 536// |   0                |  !=0     |  !=0*      | Method call    |
 537// +--------------------+----------+------------+----------------+
 538//  * For Metrowerks, this can be 0. (first virtual function in a 
 539//       single_inheritance class).
 540// When stored stored inside a specific delegate, the 'dontcare' entries are replaced
 541// with a reference to the delegate itself. This complicates the = and == operators
 542// for the delegate class.
 543
 544//          DelegateMemento - Evil version
 545//
 546// For compilers where data pointers are at least as big as code pointers, it is 
 547// possible to store the function pointer in the this pointer, using another 
 548// horrible_cast. In this case the DelegateMemento implementation is simple:
 549// +--pThis --+-- pMemFunc-+-- Meaning---------------------+
 550// |    0     |  0         | Empty                         |
 551// |  !=0     |  !=0*      | Static function or method call|
 552// +----------+------------+-------------------------------+
 553//  * For Metrowerks, this can be 0. (first virtual function in a 
 554//       single_inheritance class).
 555// Note that the Sun C++ and MSVC documentation explicitly state that they 
 556// support static_cast between void * and function pointers.
 557
 558class DelegateMemento {
 559protected: 
 560   // the data is protected, not private, because many
 561   // compilers have problems with template friends.
 562   typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.
 563   detail::GenericClass *m_pthis;
 564   GenericMemFuncType m_pFunction;
 565
 566#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 567   typedef void (*GenericFuncPtr)(); // arbitrary code pointer
 568   GenericFuncPtr m_pStaticFunction;
 569#endif
 570
 571public:
 572#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 573   DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
 574   void clear() {
 575      m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
 576   }
 577#else
 578   DelegateMemento() : m_pthis(0), m_pFunction(0) {};
 579   void clear() { m_pthis=0; m_pFunction=0;  }
 580#endif
 581public:
 582#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 583   inline bool IsEqual (const DelegateMemento &x) const{
 584       // We have to cope with the static function pointers as a special case
 585      if (m_pFunction!=x.m_pFunction) return false;
 586      // the static function ptrs must either both be equal, or both be 0.
 587      if (m_pStaticFunction!=x.m_pStaticFunction) return false;
 588      if (m_pStaticFunction!=0) return m_pthis==x.m_pthis;
 589      else return true;
 590   }
 591#else // Evil Method
 592   inline bool IsEqual (const DelegateMemento &x) const{
 593      return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
 594   }
 595#endif
 596   // Provide a strict weak ordering for DelegateMementos.
 597   inline bool IsLess(const DelegateMemento &right) const {
 598      // deal with static function pointers first
 599#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 600      if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) 
 601            return m_pStaticFunction < right.m_pStaticFunction;
 602#endif
 603      if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis;
 604   // There are no ordering operators for member function pointers, 
 605   // but we can fake one by comparing each byte. The resulting ordering is
 606   // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
 607      return dMemcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
 608
 609   }
 610   // BUGFIX (Mar 2005):
 611   // We can't just compare m_pFunction because on Metrowerks,
 612   // m_pFunction can be zero even if the delegate is not empty!
 613   inline bool operator !() const     // Is it bound to anything?
 614   { return m_pthis==0 && m_pFunction==0; }
 615   inline bool empty() const     // Is it bound to anything?
 616   { return m_pthis==0 && m_pFunction==0; }
 617public:
 618   DelegateMemento & operator =(const DelegateMemento &right)  {
 619      SetMementoFrom(right); 
 620      return *this;
 621   }
 622   inline bool operator<(const DelegateMemento &right) {
 623      return IsLess(right);
 624   }
 625   inline bool operator>(const DelegateMemento &right) {
 626      return right.IsLess(*this);
 627   }
 628   DelegateMemento (const DelegateMemento &right)  : 
 629      m_pthis(right.m_pthis), m_pFunction(right.m_pFunction)
 630#FASTDELEGATE_USESTATICFUNCTIONHACK)
 631      , m_pStaticFunction (right.m_pStaticFunction)
 632#endif
 633      {}
 634protected:
 635   void SetMementoFrom(const DelegateMemento &right)  {
 636      m_pFunction = right.m_pFunction;
 637      m_pthis = right.m_pthis;
 638#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 639      m_pStaticFunction = right.m_pStaticFunction;
 640#endif
 641   }
 642};
 643
 644
 645//                ClosurePtr<>
 646//
 647// A private wrapper class that adds function signatures to DelegateMemento.
 648// It's the class that does most of the actual work.
 649// The signatures are specified by:
 650// GenericMemFunc: must be a type of GenericClass member function pointer. 
 651// StaticFuncPtr:  must be a type of function pointer with the same signature 
 652//                 as GenericMemFunc.
 653// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
 654//                 where it never returns void (returns DefaultVoid instead).
 655
 656// An outer class, FastDelegateN<>, handles the invoking and creates the
 657// necessary typedefs.
 658// This class does everything else.
 659
 660namespace detail {
 661
 662template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
 663class ClosurePtr : public DelegateMemento {
 664public:
 665   // These functions are for setting the delegate to a member function.
 666
 667   // Here's the clever bit: we convert an arbitrary member function into a 
 668   // standard form. XMemFunc should be a member function of class X, but I can't 
 669   // enforce that here. It needs to be enforced by the wrapper class.
 670   template < class X, class XMemFunc >
 671   inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) {
 672      m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
 673         ::Convert(pthis, function_to_bind, m_pFunction);
 674#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 675      m_pStaticFunction = 0;
 676#endif
 677   }
 678   // For const member functions, we only need a const class pointer.
 679   // Since we know that the member function is const, it's safe to 
 680   // remove the const qualifier from the 'this' pointer with a const_cast.
 681   // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
 682   template < class X, class XMemFunc>
 683   inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) {
 684      m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
 685         ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
 686#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 687      m_pStaticFunction = 0;
 688#endif
 689   }
 690#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates
 691   template < class X, class XMemFunc>
 692   inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) {
 693      bindconstmemfunc(pthis, function_to_bind);
 694#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 695      m_pStaticFunction = 0;
 696#endif
 697   }
 698#endif
 699   // These functions are required for invoking the stored function
 700   inline GenericClass *GetClosureThis() const { return m_pthis; }
 701   inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
 702
 703// There are a few ways of dealing with static function pointers.
 704// There's a standard-compliant, but tricky method.
 705// There's also a straightforward hack, that won't work on DOS compilers using the
 706// medium memory model. It's so evil that I can't recommend it, but I've
 707// implemented it anyway because it produces very nice asm code.
 708
 709#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 710
 711//          ClosurePtr<> - Safe version
 712//
 713// This implementation is standard-compliant, but a bit tricky.
 714// I store the function pointer inside the class, and the delegate then
 715// points to itself. Whenever the delegate is copied, these self-references
 716// must be transformed, and this complicates the = and == operators.
 717public:
 718   // The next two functions are for operator ==, =, and the copy constructor.
 719   // We may need to convert the m_pthis pointers, so that
 720   // they remain as self-references.
 721   template< class DerivedClass >
 722   inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) {
 723      SetMementoFrom(x);
 724      if (m_pStaticFunction!=0) {
 725         // transform self references...
 726         m_pthis=reinterpret_cast<GenericClass *>(pParent);
 727      }
 728   }
 729   // For static functions, the 'static_function_invoker' class in the parent 
 730   // will be called. The parent then needs to call GetStaticFunction() to find out 
 731   // the actual function to invoke.
 732   template < class DerivedClass, class ParentInvokerSig >
 733   inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
 734            StaticFuncPtr function_to_bind ) {
 735      if (function_to_bind==0) { // cope with assignment to 0
 736         m_pFunction=0;
 737      } else { 
 738         bindmemfunc(pParent, static_function_invoker);
 739        }
 740      m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
 741   }
 742   inline UnvoidStaticFuncPtr GetStaticFunction() const { 
 743      return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction); 
 744   }
 745#else
 746
 747//          ClosurePtr<> - Evil version
 748//
 749// For compilers where data pointers are at least as big as code pointers, it is 
 750// possible to store the function pointer in the this pointer, using another 
 751// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
 752// speeds up comparison and assignment. If C++ provided direct language support
 753// for delegates, they would produce asm code that was almost identical to this.
 754// Note that the Sun C++ and MSVC documentation explicitly state that they 
 755// support static_cast between void * and function pointers.
 756
 757   template< class DerivedClass >
 758   inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) {
 759      SetMementoFrom(right);
 760   }
 761   // For static functions, the 'static_function_invoker' class in the parent 
 762   // will be called. The parent then needs to call GetStaticFunction() to find out 
 763   // the actual function to invoke.
 764   // ******** EVIL, EVIL CODE! *******
 765   template <  class DerivedClass, class ParentInvokerSig>
 766   inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
 767            StaticFuncPtr function_to_bind) {
 768      if (function_to_bind==0) { // cope with assignment to 0
 769         m_pFunction=0;
 770      } else { 
 771         // We'll be ignoring the 'this' pointer, but we need to make sure we pass
 772         // a valid value to bindmemfunc().
 773         bindmemfunc(pParent, static_function_invoker);
 774        }
 775
 776      // WARNING! Evil hack. We store the function in the 'this' pointer!
 777      // Ensure that there's a compilation failure if function pointers 
 778      // and data pointers have different sizes.
 779      // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
 780      typedef S32 ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
 781      m_pthis = horrible_cast<GenericClass *>(function_to_bind);
 782      // MSVC, SunC++ and DMC accept the following (non-standard) code:
 783//    m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
 784      // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
 785//    m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
 786   }
 787   // ******** EVIL, EVIL CODE! *******
 788   // This function will be called with an invalid 'this' pointer!!
 789   // We're just returning the 'this' pointer, converted into
 790   // a function pointer!
 791   inline UnvoidStaticFuncPtr GetStaticFunction() const {
 792      // Ensure that there's a compilation failure if function pointers 
 793      // and data pointers have different sizes.
 794      // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
 795      typedef S32 ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
 796      return horrible_cast<UnvoidStaticFuncPtr>(this);
 797   }
 798#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
 799
 800   // Does the closure contain this static function?
 801   inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){
 802      if (funcptr==0) return empty(); 
 803   // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
 804   // value that is not equal to any valid function pointer.
 805      else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
 806   }
 807};
 808
 809
 810} // namespace detail
 811
 812////////////////////////////////////////////////////////////////////////////////
 813//                Fast Delegates, part 3:
 814//
 815//          Wrapper classes to ensure type safety
 816//
 817////////////////////////////////////////////////////////////////////////////////
 818
 819
 820// Once we have the member function conversion templates, it's easy to make the
 821// wrapper classes. So that they will work with as many compilers as possible, 
 822// the classes are of the form
 823//   FastDelegate3<int, char *, double>
 824// They can cope with any combination of parameters. The max number of parameters
 825// allowed is 8, but it is trivial to increase this limit.
 826// Note that we need to treat const member functions seperately.
 827// All this class does is to enforce type safety, and invoke the delegate with
 828// the correct list of parameters.
 829
 830// Because of the weird rule about the class of derived member function pointers,
 831// you sometimes need to apply a downcast to the 'this' pointer.
 832// This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below. 
 833// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
 834// without this trick you'd need to write:
 835//    MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
 836// but with the trick you can write
 837//    MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
 838
 839// RetType is the type the compiler uses in compiling the template. For VC6,
 840// it cannot be void. DesiredRetType is the real type which is returned from
 841// all of the functions. It can be void.
 842
 843// Implicit conversion to "bool" is achieved using the safe_bool idiom,
 844// using member data pointers (MDP). This allows "if (dg)..." syntax
 845// Because some compilers (eg codeplay) don't have a unique value for a zero
 846// MDP, an extra padding member is added to the SafeBool struct.
 847// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
 848// in that case the static function constructor is not made explicit; this
 849// allows "if (dg==0) ..." to compile.
 850
 851//N=0
 852template<class RetType=detail::DefaultVoid>
 853class FastDelegate0 {
 854private:
 855   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
 856   typedef DesiredRetType (*StaticFunctionPtr)();
 857   typedef RetType (*UnvoidStaticFunctionPtr)();
 858   typedef RetType (detail::GenericClass::*GenericMemFn)();
 859   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
 860   ClosureType m_Closure;
 861public:
 862   // Typedefs to aid generic programming
 863   typedef FastDelegate0 type;
 864
 865   // Construction and comparison functions
 866   FastDelegate0() { clear(); }
 867   FastDelegate0(const FastDelegate0 &x) {
 868      m_Closure.CopyFrom(this, x.m_Closure); }
 869   void operator =(const FastDelegate0 &x)  {
 870      m_Closure.CopyFrom(this, x.m_Closure); }
 871   bool operator==(const FastDelegate0 &x) const {
 872      return m_Closure.IsEqual(x.m_Closure); }
 873   bool operator!=(const FastDelegate0 &x) const {
 874      return !m_Closure.IsEqual(x.m_Closure); }
 875   bool operator<(const FastDelegate0 &x) const {
 876      return m_Closure.IsLess(x.m_Closure);  }
 877   bool operator>(const FastDelegate0 &x) const {
 878      return x.m_Closure.IsLess(m_Closure);  }
 879   // Binding to non-const member functions
 880   template < class X, class Y >
 881   FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) {
 882      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
 883   template < class X, class Y >
 884   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) {
 885      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
 886   // Binding to const member functions.
 887   template < class X, class Y >
 888   FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
 889      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
 890   template < class X, class Y >
 891   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
 892      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
 893   // Static functions. We convert them into a member function call.
 894   // This constructor also provides implicit conversion
 895   FastDelegate0(DesiredRetType (*function_to_bind)() ) {
 896      bind(function_to_bind); }
 897   // for efficiency, prevent creation of a temporary
 898   void operator =(DesiredRetType (*function_to_bind)() ) {
 899      bind(function_to_bind); }
 900   inline void bind(DesiredRetType (*function_to_bind)()) {
 901      m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, 
 902         function_to_bind); }
 903   // Invoke the delegate
 904   RetType operator()() const {
 905   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); }
 906   // Implicit conversion to "bool" using the safe_bool idiom
 907private:
 908   typedef struct SafeBoolStruct {
 909      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
 910      StaticFunctionPtr m_nonzero;
 911   } UselessTypedef;
 912    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
 913public:
 914   operator unspecified_bool_type() const {
 915        return empty()? 0: &SafeBoolStruct::m_nonzero;
 916    }
 917   // necessary to allow ==0 to work despite the safe_bool idiom
 918   inline bool operator==(StaticFunctionPtr funcptr) {
 919      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
 920   inline bool operator!=(StaticFunctionPtr funcptr) { 
 921      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
 922   inline bool operator !() const  {  // Is it bound to anything?
 923         return !m_Closure; }
 924   inline bool empty() const  {
 925         return !m_Closure; }
 926   void clear() { m_Closure.clear();}
 927   // Conversion to and from the DelegateMemento storage class
 928   const DelegateMemento & GetMemento() { return m_Closure; }
 929   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
 930
 931private: // Invoker for static functions
 932   RetType InvokeStaticFunction() const {
 933   return (*(m_Closure.GetStaticFunction()))(); }
 934};
 935
 936//N=1
 937template<class Param1, class RetType=detail::DefaultVoid>
 938class FastDelegate1 {
 939private:
 940   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
 941   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
 942   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
 943   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1);
 944   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
 945   ClosureType m_Closure;
 946public:
 947   // Typedefs to aid generic programming
 948   typedef FastDelegate1 type;
 949
 950   // Construction and comparison functions
 951   FastDelegate1() { clear(); }
 952   FastDelegate1(const FastDelegate1 &x) {
 953      m_Closure.CopyFrom(this, x.m_Closure); }
 954   void operator =(const FastDelegate1 &x)  {
 955      m_Closure.CopyFrom(this, x.m_Closure); }
 956   bool operator==(const FastDelegate1 &x) const {
 957      return m_Closure.IsEqual(x.m_Closure); }
 958   bool operator!=(const FastDelegate1 &x) const {
 959      return !m_Closure.IsEqual(x.m_Closure); }
 960   bool operator<(const FastDelegate1 &x) const {
 961      return m_Closure.IsLess(x.m_Closure);  }
 962   bool operator>(const FastDelegate1 &x) const {
 963      return x.m_Closure.IsLess(m_Closure);  }
 964   // Binding to non-const member functions
 965   template < class X, class Y >
 966   FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) {
 967      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
 968   template < class X, class Y >
 969   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) {
 970      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
 971   // Binding to const member functions.
 972   template < class X, class Y >
 973   FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
 974      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
 975   template < class X, class Y >
 976   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
 977      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
 978   // Static functions. We convert them into a member function call.
 979   // This constructor also provides implicit conversion
 980   FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) {
 981      bind(function_to_bind); }
 982   // for efficiency, prevent creation of a temporary
 983   void operator =(DesiredRetType (*function_to_bind)(Param1 p1) ) {
 984      bind(function_to_bind); }
 985   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) {
 986      m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, 
 987         function_to_bind); }
 988   // Invoke the delegate
 989   RetType operator()(Param1 p1) const {
 990   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); }
 991   // Implicit conversion to "bool" using the safe_bool idiom
 992private:
 993   typedef struct SafeBoolStruct {
 994      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
 995      StaticFunctionPtr m_nonzero;
 996   } UselessTypedef;
 997    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
 998public:
 999   operator unspecified_bool_type() const {
1000        return empty()? 0: &SafeBoolStruct::m_nonzero;
1001    }
1002   // necessary to allow ==0 to work despite the safe_bool idiom
1003   inline bool operator==(StaticFunctionPtr funcptr) {
1004      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1005   inline bool operator!=(StaticFunctionPtr funcptr) { 
1006      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1007   inline bool operator !() const  {  // Is it bound to anything?
1008         return !m_Closure; }
1009   inline bool empty() const  {
1010         return !m_Closure; }
1011   void clear() { m_Closure.clear();}
1012   // Conversion to and from the DelegateMemento storage class
1013   const DelegateMemento & GetMemento() { return m_Closure; }
1014   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1015
1016private: // Invoker for static functions
1017   RetType InvokeStaticFunction(Param1 p1) const {
1018   return (*(m_Closure.GetStaticFunction()))(p1); }
1019};
1020
1021//N=2
1022template<class Param1, class Param2, class RetType=detail::DefaultVoid>
1023class FastDelegate2 {
1024private:
1025   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1026   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
1027   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
1028   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
1029   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1030   ClosureType m_Closure;
1031public:
1032   // Typedefs to aid generic programming
1033   typedef FastDelegate2 type;
1034
1035   // Construction and comparison functions
1036   FastDelegate2() { clear(); }
1037   FastDelegate2(const FastDelegate2 &x) {
1038      m_Closure.CopyFrom(this, x.m_Closure); }
1039   void operator =(const FastDelegate2 &x)  {
1040      m_Closure.CopyFrom(this, x.m_Closure); }
1041   bool operator==(const FastDelegate2 &x) const {
1042      return m_Closure.IsEqual(x.m_Closure); }
1043   bool operator!=(const FastDelegate2 &x) const {
1044      return !m_Closure.IsEqual(x.m_Closure); }
1045   bool operator<(const FastDelegate2 &x) const {
1046      return m_Closure.IsLess(x.m_Closure);  }
1047   bool operator>(const FastDelegate2 &x) const {
1048      return x.m_Closure.IsLess(m_Closure);  }
1049   // Binding to non-const member functions
1050   template < class X, class Y >
1051   FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) {
1052      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1053   template < class X, class Y >
1054   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) {
1055      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1056   // Binding to const member functions.
1057   template < class X, class Y >
1058   FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
1059      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1060   template < class X, class Y >
1061   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
1062      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1063   // Static functions. We convert them into a member function call.
1064   // This constructor also provides implicit conversion
1065   FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
1066      bind(function_to_bind); }
1067   // for efficiency, prevent creation of a temporary
1068   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
1069      bind(function_to_bind); }
1070   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) {
1071      m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, 
1072         function_to_bind); }
1073   // Invoke the delegate
1074   RetType operator()(Param1 p1, Param2 p2) const {
1075   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); }
1076   // Implicit conversion to "bool" using the safe_bool idiom
1077private:
1078   typedef struct SafeBoolStruct {
1079      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1080      StaticFunctionPtr m_nonzero;
1081   } UselessTypedef;
1082    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1083public:
1084   operator unspecified_bool_type() const {
1085        return empty()? 0: &SafeBoolStruct::m_nonzero;
1086    }
1087   // necessary to allow ==0 to work despite the safe_bool idiom
1088   inline bool operator==(StaticFunctionPtr funcptr) {
1089      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1090   inline bool operator!=(StaticFunctionPtr funcptr) { 
1091      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1092   inline bool operator !() const  {  // Is it bound to anything?
1093         return !m_Closure; }
1094   inline bool empty() const  {
1095         return !m_Closure; }
1096   void clear() { m_Closure.clear();}
1097   // Conversion to and from the DelegateMemento storage class
1098   const DelegateMemento & GetMemento() { return m_Closure; }
1099   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1100
1101private: // Invoker for static functions
1102   RetType InvokeStaticFunction(Param1 p1, Param2 p2) const {
1103   return (*(m_Closure.GetStaticFunction()))(p1, p2); }
1104};
1105
1106//N=3
1107template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
1108class FastDelegate3 {
1109private:
1110   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1111   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
1112   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
1113   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
1114   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1115   ClosureType m_Closure;
1116public:
1117   // Typedefs to aid generic programming
1118   typedef FastDelegate3 type;
1119
1120   // Construction and comparison functions
1121   FastDelegate3() { clear(); }
1122   FastDelegate3(const FastDelegate3 &x) {
1123      m_Closure.CopyFrom(this, x.m_Closure); }
1124   void operator =(const FastDelegate3 &x)  {
1125      m_Closure.CopyFrom(this, x.m_Closure); }
1126   bool operator==(const FastDelegate3 &x) const {
1127      return m_Closure.IsEqual(x.m_Closure); }
1128   bool operator!=(const FastDelegate3 &x) const {
1129      return !m_Closure.IsEqual(x.m_Closure); }
1130   bool operator<(const FastDelegate3 &x) const {
1131      return m_Closure.IsLess(x.m_Closure);  }
1132   bool operator>(const FastDelegate3 &x) const {
1133      return x.m_Closure.IsLess(m_Closure);  }
1134   // Binding to non-const member functions
1135   template < class X, class Y >
1136   FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
1137      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1138   template < class X, class Y >
1139   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
1140      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1141   // Binding to const member functions.
1142   template < class X, class Y >
1143   FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
1144      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1145   template < class X, class Y >
1146   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
1147      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1148   // Static functions. We convert them into a member function call.
1149   // This constructor also provides implicit conversion
1150   FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
1151      bind(function_to_bind); }
1152   // for efficiency, prevent creation of a temporary
1153   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
1154      bind(function_to_bind); }
1155   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
1156      m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, 
1157         function_to_bind); }
1158   // Invoke the delegate
1159   RetType operator()(Param1 p1, Param2 p2, Param3 p3) const {
1160   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); }
1161   // Implicit conversion to "bool" using the safe_bool idiom
1162private:
1163   typedef struct SafeBoolStruct {
1164      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1165      StaticFunctionPtr m_nonzero;
1166   } UselessTypedef;
1167    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1168public:
1169   operator unspecified_bool_type() const {
1170        return empty()? 0: &SafeBoolStruct::m_nonzero;
1171    }
1172   // necessary to allow ==0 to work despite the safe_bool idiom
1173   inline bool operator==(StaticFunctionPtr funcptr) {
1174      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1175   inline bool operator!=(StaticFunctionPtr funcptr) { 
1176      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1177   inline bool operator !() const  {  // Is it bound to anything?
1178         return !m_Closure; }
1179   inline bool empty() const  {
1180         return !m_Closure; }
1181   void clear() { m_Closure.clear();}
1182   // Conversion to and from the DelegateMemento storage class
1183   const DelegateMemento & GetMemento() { return m_Closure; }
1184   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1185
1186private: // Invoker for static functions
1187   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const {
1188   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); }
1189};
1190
1191//N=4
1192template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
1193class FastDelegate4 {
1194private:
1195   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1196   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
1197   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
1198   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
1199   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1200   ClosureType m_Closure;
1201public:
1202   // Typedefs to aid generic programming
1203   typedef FastDelegate4 type;
1204
1205   // Construction and comparison functions
1206   FastDelegate4() { clear(); }
1207   FastDelegate4(const FastDelegate4 &x) {
1208      m_Closure.CopyFrom(this, x.m_Closure); }
1209   void operator =(const FastDelegate4 &x)  {
1210      m_Closure.CopyFrom(this, x.m_Closure); }
1211   bool operator==(const FastDelegate4 &x) const {
1212      return m_Closure.IsEqual(x.m_Closure); }
1213   bool operator!=(const FastDelegate4 &x) const {
1214      return !m_Closure.IsEqual(x.m_Closure); }
1215   bool operator<(const FastDelegate4 &x) const {
1216      return m_Closure.IsLess(x.m_Closure);  }
1217   bool operator>(const FastDelegate4 &x) const {
1218      return x.m_Closure.IsLess(m_Closure);  }
1219   // Binding to non-const member functions
1220   template < class X, class Y >
1221   FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
1222      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1223   template < class X, class Y >
1224   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
1225      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1226   // Binding to const member functions.
1227   template < class X, class Y >
1228   FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
1229      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1230   template < class X, class Y >
1231   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
1232      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1233   // Static functions. We convert them into a member function call.
1234   // This constructor also provides implicit conversion
1235   FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
1236      bind(function_to_bind); }
1237   // for efficiency, prevent creation of a temporary
1238   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
1239      bind(function_to_bind); }
1240   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
1241      m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, 
1242         function_to_bind); }
1243   // Invoke the delegate
1244   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
1245   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); }
1246   // Implicit conversion to "bool" using the safe_bool idiom
1247private:
1248   typedef struct SafeBoolStruct {
1249      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1250      StaticFunctionPtr m_nonzero;
1251   } UselessTypedef;
1252    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1253public:
1254   operator unspecified_bool_type() const {
1255        return empty()? 0: &SafeBoolStruct::m_nonzero;
1256    }
1257   // necessary to allow ==0 to work despite the safe_bool idiom
1258   inline bool operator==(StaticFunctionPtr funcptr) {
1259      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1260   inline bool operator!=(StaticFunctionPtr funcptr) { 
1261      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1262   inline bool operator !() const  {  // Is it bound to anything?
1263         return !m_Closure; }
1264   inline bool empty() const  {
1265         return !m_Closure; }
1266   void clear() { m_Closure.clear();}
1267   // Conversion to and from the DelegateMemento storage class
1268   const DelegateMemento & GetMemento() { return m_Closure; }
1269   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1270
1271private: // Invoker for static functions
1272   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
1273   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); }
1274};
1275
1276//N=5
1277template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
1278class FastDelegate5 {
1279private:
1280   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1281   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
1282   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
1283   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
1284   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1285   ClosureType m_Closure;
1286public:
1287   // Typedefs to aid generic programming
1288   typedef FastDelegate5 type;
1289
1290   // Construction and comparison functions
1291   FastDelegate5() { clear(); }
1292   FastDelegate5(const FastDelegate5 &x) {
1293      m_Closure.CopyFrom(this, x.m_Closure); }
1294   void operator =(const FastDelegate5 &x)  {
1295      m_Closure.CopyFrom(this, x.m_Closure); }
1296   bool operator==(const FastDelegate5 &x) const {
1297      return m_Closure.IsEqual(x.m_Closure); }
1298   bool operator!=(const FastDelegate5 &x) const {
1299      return !m_Closure.IsEqual(x.m_Closure); }
1300   bool operator<(const FastDelegate5 &x) const {
1301      return m_Closure.IsLess(x.m_Closure);  }
1302   bool operator>(const FastDelegate5 &x) const {
1303      return x.m_Closure.IsLess(m_Closure);  }
1304   // Binding to non-const member functions
1305   template < class X, class Y >
1306   FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
1307      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1308   template < class X, class Y >
1309   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
1310      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1311   // Binding to const member functions.
1312   template < class X, class Y >
1313   FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
1314      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1315   template < class X, class Y >
1316   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
1317      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1318   // Static functions. We convert them into a member function call.
1319   // This constructor also provides implicit conversion
1320   FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
1321      bind(function_to_bind); }
1322   // for efficiency, prevent creation of a temporary
1323   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
1324      bind(function_to_bind); }
1325   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
1326      m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, 
1327         function_to_bind); }
1328   // Invoke the delegate
1329   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
1330   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); }
1331   // Implicit conversion to "bool" using the safe_bool idiom
1332private:
1333   typedef struct SafeBoolStruct {
1334      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1335      StaticFunctionPtr m_nonzero;
1336   } UselessTypedef;
1337    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1338public:
1339   operator unspecified_bool_type() const {
1340        return empty()? 0: &SafeBoolStruct::m_nonzero;
1341    }
1342   // necessary to allow ==0 to work despite the safe_bool idiom
1343   inline bool operator==(StaticFunctionPtr funcptr) {
1344      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1345   inline bool operator!=(StaticFunctionPtr funcptr) { 
1346      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1347   inline bool operator !() const  {  // Is it bound to anything?
1348         return !m_Closure; }
1349   inline bool empty() const  {
1350         return !m_Closure; }
1351   void clear() { m_Closure.clear();}
1352   // Conversion to and from the DelegateMemento storage class
1353   const DelegateMemento & GetMemento() { return m_Closure; }
1354   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1355
1356private: // Invoker for static functions
1357   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
1358   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); }
1359};
1360
1361//N=6
1362template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
1363class FastDelegate6 {
1364private:
1365   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1366   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
1367   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
1368   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
1369   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1370   ClosureType m_Closure;
1371public:
1372   // Typedefs to aid generic programming
1373   typedef FastDelegate6 type;
1374
1375   // Construction and comparison functions
1376   FastDelegate6() { clear(); }
1377   FastDelegate6(const FastDelegate6 &x) {
1378      m_Closure.CopyFrom(this, x.m_Closure); }
1379   void operator =(const FastDelegate6 &x)  {
1380      m_Closure.CopyFrom(this, x.m_Closure); }
1381   bool operator==(const FastDelegate6 &x) const {
1382      return m_Closure.IsEqual(x.m_Closure); }
1383   bool operator!=(const FastDelegate6 &x) const {
1384      return !m_Closure.IsEqual(x.m_Closure); }
1385   bool operator<(const FastDelegate6 &x) const {
1386      return m_Closure.IsLess(x.m_Closure);  }
1387   bool operator>(const FastDelegate6 &x) const {
1388      return x.m_Closure.IsLess(m_Closure);  }
1389   // Binding to non-const member functions
1390   template < class X, class Y >
1391   FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
1392      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1393   template < class X, class Y >
1394   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
1395      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1396   // Binding to const member functions.
1397   template < class X, class Y >
1398   FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
1399      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1400   template < class X, class Y >
1401   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
1402      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1403   // Static functions. We convert them into a member function call.
1404   // This constructor also provides implicit conversion
1405   FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
1406      bind(function_to_bind); }
1407   // for efficiency, prevent creation of a temporary
1408   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
1409      bind(function_to_bind); }
1410   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
1411      m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, 
1412         function_to_bind); }
1413   // Invoke the delegate
1414   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
1415   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); }
1416   // Implicit conversion to "bool" using the safe_bool idiom
1417private:
1418   typedef struct SafeBoolStruct {
1419      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1420      StaticFunctionPtr m_nonzero;
1421   } UselessTypedef;
1422    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1423public:
1424   operator unspecified_bool_type() const {
1425        return empty()? 0: &SafeBoolStruct::m_nonzero;
1426    }
1427   // necessary to allow ==0 to work despite the safe_bool idiom
1428   inline bool operator==(StaticFunctionPtr funcptr) {
1429      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1430   inline bool operator!=(StaticFunctionPtr funcptr) { 
1431      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1432   inline bool operator !() const  {  // Is it bound to anything?
1433         return !m_Closure; }
1434   inline bool empty() const  {
1435         return !m_Closure; }
1436   void clear() { m_Closure.clear();}
1437   // Conversion to and from the DelegateMemento storage class
1438   const DelegateMemento & GetMemento() { return m_Closure; }
1439   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1440
1441private: // Invoker for static functions
1442   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
1443   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); }
1444};
1445
1446//N=7
1447template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
1448class FastDelegate7 {
1449private:
1450   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1451   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
1452   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
1453   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
1454   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1455   ClosureType m_Closure;
1456public:
1457   // Typedefs to aid generic programming
1458   typedef FastDelegate7 type;
1459
1460   // Construction and comparison functions
1461   FastDelegate7() { clear(); }
1462   FastDelegate7(const FastDelegate7 &x) {
1463      m_Closure.CopyFrom(this, x.m_Closure); }
1464   void operator =(const FastDelegate7 &x)  {
1465      m_Closure.CopyFrom(this, x.m_Closure); }
1466   bool operator==(const FastDelegate7 &x) const {
1467      return m_Closure.IsEqual(x.m_Closure); }
1468   bool operator!=(const FastDelegate7 &x) const {
1469      return !m_Closure.IsEqual(x.m_Closure); }
1470   bool operator<(const FastDelegate7 &x) const {
1471      return m_Closure.IsLess(x.m_Closure);  }
1472   bool operator>(const FastDelegate7 &x) const {
1473      return x.m_Closure.IsLess(m_Closure);  }
1474   // Binding to non-const member functions
1475   template < class X, class Y >
1476   FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
1477      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1478   template < class X, class Y >
1479   inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
1480      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1481   // Binding to const member functions.
1482   template < class X, class Y >
1483   FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
1484      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1485   template < class X, class Y >
1486   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) {
1487      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1488   // Static functions. We convert them into a member function call.
1489   // This constructor also provides implicit conversion
1490   FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
1491      bind(function_to_bind); }
1492   // for efficiency, prevent creation of a temporary
1493   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
1494      bind(function_to_bind); }
1495   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
1496      m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, 
1497         function_to_bind); }
1498   // Invoke the delegate
1499   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
1500   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); }
1501   // Implicit conversion to "bool" using the safe_bool idiom
1502private:
1503   typedef struct SafeBoolStruct {
1504      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1505      StaticFunctionPtr m_nonzero;
1506   } UselessTypedef;
1507    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1508public:
1509   operator unspecified_bool_type() const {
1510        return empty()? 0: &SafeBoolStruct::m_nonzero;
1511    }
1512   // necessary to allow ==0 to work despite the safe_bool idiom
1513   inline bool operator==(StaticFunctionPtr funcptr) {
1514      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1515   inline bool operator!=(StaticFunctionPtr funcptr) { 
1516      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1517   inline bool operator !() const  {  // Is it bound to anything?
1518         return !m_Closure; }
1519   inline bool empty() const  {
1520         return !m_Closure; }
1521   void clear() { m_Closure.clear();}
1522   // Conversion to and from the DelegateMemento storage class
1523   const DelegateMemento & GetMemento() { return m_Closure; }
1524   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1525
1526private: // Invoker for static functions
1527   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
1528   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); }
1529};
1530
1531//N=8
1532template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
1533class FastDelegate8 {
1534private:
1535   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1536   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
1537   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
1538   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
1539   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1540   ClosureType m_Closure;
1541public:
1542   // Typedefs to aid generic programming
1543   typedef FastDelegate8 type;
1544
1545   // Construction and comparison functions
1546   FastDelegate8() { clear(); }
1547   FastDelegate8(const FastDelegate8 &x) {
1548      m_Closure.CopyFrom(this, x.m_Closure); }
1549   void operator =(const FastDelegate8 &x)  {
1550      m_Closure.CopyFrom(this, x.m_Closure); }
1551   bool operator==(const FastDelegate8 &x) const {
1552      return m_Closure.IsEqual(x.m_Closure); }
1553   bool operator!=(const FastDelegate8 &x) const {
1554      return !m_Closure.IsEqual(x.m_Closure); }
1555   bool operator<(const FastDelegate8 &x) const {
1556      return m_Closure.IsLess(x.m_Closure);  }
1557   bool operator>(const FastDelegate8 &x) const {
1558      return x.m_Closure.IsLess(m_Closure);  }
1559   // Binding to non-const member functions
1560   template < class X, class Y >
1561   FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
1562      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1563   template < class X, class Y >
1564   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)) {
1565      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1566   // Binding to const member functions.
1567   template < class X, class Y >
1568   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) {
1569      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1570   template < class X, class Y >
1571   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) {
1572      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1573   // Static functions. We convert them into a member function call.
1574   // This constructor also provides implicit conversion
1575   FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
1576      bind(function_to_bind); }
1577   // for efficiency, prevent creation of a temporary
1578   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
1579      bind(function_to_bind); }
1580   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
1581      m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, 
1582         function_to_bind); }
1583   // Invoke the delegate
1584   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
1585   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); }
1586   // Implicit conversion to "bool" using the safe_bool idiom
1587private:
1588   typedef struct SafeBoolStruct {
1589      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1590      StaticFunctionPtr m_nonzero;
1591   } UselessTypedef;
1592    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1593public:
1594   operator unspecified_bool_type() const {
1595        return empty()? 0: &SafeBoolStruct::m_nonzero;
1596    }
1597   // necessary to allow ==0 to work despite the safe_bool idiom
1598   inline bool operator==(StaticFunctionPtr funcptr) {
1599      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1600   inline bool operator!=(StaticFunctionPtr funcptr) { 
1601      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1602   inline bool operator !() const  {  // Is it bound to anything?
1603         return !m_Closure; }
1604   inline bool empty() const  {
1605         return !m_Closure; }
1606   void clear() { m_Closure.clear();}
1607   // Conversion to and from the DelegateMemento storage class
1608   const DelegateMemento & GetMemento() { return m_Closure; }
1609   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1610
1611private: // Invoker for static functions
1612   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
1613   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); }
1614};
1615
1616//N=11
1617template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class RetType=detail::DefaultVoid>
1618class FastDelegate11 {
1619private:
1620   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1621   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11);
1622   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11);
1623   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11);
1624   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1625   ClosureType m_Closure;
1626public:
1627   // Typedefs to aid generic programming
1628   typedef FastDelegate11 type;
1629
1630   // Construction and comparison functions
1631   FastDelegate11() { clear(); }
1632   FastDelegate11(const FastDelegate11 &x) {
1633      m_Closure.CopyFrom(this, x.m_Closure); }
1634   void operator =(const FastDelegate11 &x)  {
1635      m_Closure.CopyFrom(this, x.m_Closure); }
1636   bool operator==(const FastDelegate11 &x) const {
1637      return m_Closure.IsEqual(x.m_Closure); }
1638   bool operator!=(const FastDelegate11 &x) const {
1639      return !m_Closure.IsEqual(x.m_Closure); }
1640   bool operator<(const FastDelegate11 &x) const {
1641      return m_Closure.IsLess(x.m_Closure);  }
1642   bool operator>(const FastDelegate11 &x) const {
1643      return x.m_Closure.IsLess(m_Closure);  }
1644   // Binding to non-const member functions
1645   template < class X, class Y >
1646   FastDelegate11(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) {
1647      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1648   template < class X, class Y >
1649   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, Param9 p9, Param10 p10, Param11 p11)) {
1650      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1651   // Binding to const member functions.
1652   template < class X, class Y >
1653   FastDelegate11(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) {
1654      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1655   template < class X, class Y >
1656   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) {
1657      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1658   // Static functions. We convert them into a member function call.
1659   // This constructor also provides implicit conversion
1660   FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) {
1661      bind(function_to_bind); }
1662   // for efficiency, prevent creation of a temporary
1663   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) {
1664      bind(function_to_bind); }
1665   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8), Param9 p9, Param10 p10, Param11 p11) {
1666      m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, 
1667         function_to_bind); }
1668   // Invoke the delegate
1669   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const {
1670   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
1671   // Implicit conversion to "bool" using the safe_bool idiom
1672private:
1673   typedef struct SafeBoolStruct {
1674      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1675      StaticFunctionPtr m_nonzero;
1676   } UselessTypedef;
1677    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1678public:
1679   operator unspecified_bool_type() const {
1680        return empty()? 0: &SafeBoolStruct::m_nonzero;
1681    }
1682   // necessary to allow ==0 to work despite the safe_bool idiom
1683   inline bool operator==(StaticFunctionPtr funcptr) {
1684      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1685   inline bool operator!=(StaticFunctionPtr funcptr) { 
1686      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1687   inline bool operator !() const  {  // Is it bound to anything?
1688         return !m_Closure; }
1689   inline bool empty() const  {
1690         return !m_Closure; }
1691   void clear() { m_Closure.clear();}
1692   // Conversion to and from the DelegateMemento storage class
1693   const DelegateMemento & GetMemento() { return m_Closure; }
1694   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1695
1696private: // Invoker for static functions
1697   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const {
1698   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
1699};
1700
1701//N=12
1702template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class RetType=detail::DefaultVoid>
1703class FastDelegate12 {
1704private:
1705   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1706   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12);
1707   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12);
1708   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12);
1709   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1710   ClosureType m_Closure;
1711public:
1712   // Typedefs to aid generic programming
1713   typedef FastDelegate12 type;
1714
1715   // Construction and comparison functions
1716   FastDelegate12() { clear(); }
1717   FastDelegate12(const FastDelegate12 &x) {
1718      m_Closure.CopyFrom(this, x.m_Closure); }
1719   void operator =(const FastDelegate12 &x)  {
1720      m_Closure.CopyFrom(this, x.m_Closure); }
1721   bool operator==(const FastDelegate12 &x) const {
1722      return m_Closure.IsEqual(x.m_Closure); }
1723   bool operator!=(const FastDelegate12 &x) const {
1724      return !m_Closure.IsEqual(x.m_Closure); }
1725   bool operator<(const FastDelegate12 &x) const {
1726      return m_Closure.IsLess(x.m_Closure);  }
1727   bool operator>(const FastDelegate12 &x) const {
1728      return x.m_Closure.IsLess(m_Closure);  }
1729   // Binding to non-const member functions
1730   template < class X, class Y >
1731   FastDelegate12(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) {
1732      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1733   template < class X, class Y >
1734   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, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) {
1735      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1736   // Binding to const member functions.
1737   template < class X, class Y >
1738   FastDelegate12(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) {
1739      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1740   template < class X, class Y >
1741   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) {
1742      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1743   // Static functions. We convert them into a member function call.
1744   // This constructor also provides implicit conversion
1745   FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) {
1746      bind(function_to_bind); }
1747   // for efficiency, prevent creation of a temporary
1748   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) {
1749      bind(function_to_bind); }
1750   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8), Param9 p9, Param10 p10, Param11 p11, Param12 p12) {
1751      m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, 
1752         function_to_bind); }
1753   // Invoke the delegate
1754   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const {
1755   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,p12); }
1756   // Implicit conversion to "bool" using the safe_bool idiom
1757private:
1758   typedef struct SafeBoolStruct {
1759      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1760      StaticFunctionPtr m_nonzero;
1761   } UselessTypedef;
1762    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1763public:
1764   operator unspecified_bool_type() const {
1765        return empty()? 0: &SafeBoolStruct::m_nonzero;
1766    }
1767   // necessary to allow ==0 to work despite the safe_bool idiom
1768   inline bool operator==(StaticFunctionPtr funcptr) {
1769      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1770   inline bool operator!=(StaticFunctionPtr funcptr) { 
1771      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1772   inline bool operator !() const  {  // Is it bound to anything?
1773         return !m_Closure; }
1774   inline bool empty() const  {
1775         return !m_Closure; }
1776   void clear() { m_Closure.clear();}
1777   // Conversion to and from the DelegateMemento storage class
1778   const DelegateMemento & GetMemento() { return m_Closure; }
1779   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1780
1781private: // Invoker for static functions
1782   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const {
1783   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
1784};
1785
1786//N=13
1787template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class RetType=detail::DefaultVoid>
1788class FastDelegate13 {
1789private:
1790   typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1791   typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13);
1792   typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13);
1793   typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13);
1794   typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1795   ClosureType m_Closure;
1796public:
1797   // Typedefs to aid generic programming
1798   typedef FastDelegate13 type;
1799
1800   // Construction and comparison functions
1801   FastDelegate13() { clear(); }
1802   FastDelegate13(const FastDelegate13 &x) {
1803      m_Closure.CopyFrom(this, x.m_Closure); }
1804   void operator =(const FastDelegate13 &x)  {
1805      m_Closure.CopyFrom(this, x.m_Closure); }
1806   bool operator==(const FastDelegate13 &x) const {
1807      return m_Closure.IsEqual(x.m_Closure); }
1808   bool operator!=(const FastDelegate13 &x) const {
1809      return !m_Closure.IsEqual(x.m_Closure); }
1810   bool operator<(const FastDelegate13 &x) const {
1811      return m_Closure.IsLess(x.m_Closure);  }
1812   bool operator>(const FastDelegate13 &x) const {
1813      return x.m_Closure.IsLess(m_Closure);  }
1814   // Binding to non-const member functions
1815   template < class X, class Y >
1816   FastDelegate13(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) {
1817      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1818   template < class X, class Y >
1819   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, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) {
1820      m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1821   // Binding to const member functions.
1822   template < class X, class Y >
1823   FastDelegate13(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) {
1824      m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);  }
1825   template < class X, class Y >
1826   inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) {
1827      m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1828   // Static functions. We convert them into a member function call.
1829   // This constructor also provides implicit conversion
1830   FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) {
1831      bind(function_to_bind); }
1832   // for efficiency, prevent creation of a temporary
1833   void operator =(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) {
1834      bind(function_to_bind); }
1835   inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8), Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) {
1836      m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, 
1837         function_to_bind); }
1838   // Invoke the delegate
1839   RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const {
1840   return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,p12,p13); }
1841   // Implicit conversion to "bool" using the safe_bool idiom
1842private:
1843   typedef struct SafeBoolStruct {
1844      S32 a_data_pointer_to_this_is_0_on_buggy_compilers;
1845      StaticFunctionPtr m_nonzero;
1846   } UselessTypedef;
1847    typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1848public:
1849   operator unspecified_bool_type() const {
1850        return empty()? 0: &SafeBoolStruct::m_nonzero;
1851    }
1852   // necessary to allow ==0 to work despite the safe_bool idiom
1853   inline bool operator==(StaticFunctionPtr funcptr) {
1854      return m_Closure.IsEqualToStaticFuncPtr(funcptr);  }
1855   inline bool operator!=(StaticFunctionPtr funcptr) { 
1856      return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
1857   inline bool operator !() const  {  // Is it bound to anything?
1858         return !m_Closure; }
1859   inline bool empty() const  {
1860         return !m_Closure; }
1861   void clear() { m_Closure.clear();}
1862   // Conversion to and from the DelegateMemento storage class
1863   const DelegateMemento & GetMemento() { return m_Closure; }
1864   void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1865
1866private: // Invoker for static functions
1867   RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const {
1868   return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); }
1869};
1870
1871
1872////////////////////////////////////////////////////////////////////////////////
1873//                Fast Delegates, part 4:
1874// 
1875//          FastDelegate<> class (Original author: Jody Hagins)
1876// Allows boost::function style syntax like:
1877//       FastDelegate< double (int, long) >
1878// instead of:
1879//       FastDelegate2< int, long, double >
1880//
1881////////////////////////////////////////////////////////////////////////////////
1882
1883#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
1884
1885// Declare FastDelegate as a class template.  It will be specialized
1886// later for all number of arguments.
1887template <typename Signature>
1888class FastDelegate;
1889
1890//N=0
1891// Specialization to allow use of
1892// FastDelegate< R (  ) >
1893// instead of 
1894// FastDelegate0 < R >
1895template<typename R>
1896class FastDelegate< R (  ) >
1897  // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
1898  : public FastDelegate0 < R >
1899{
1900public:
1901  // Make using the base type a bit easier via typedef.
1902  typedef FastDelegate0 < R> BaseType;
1903
1904  // Allow users access to the specific type of this delegate.
1905  typedef FastDelegate SelfType;
1906
1907  // Mimic the base class constructors.
1908  FastDelegate() : BaseType() { }
1909
1910  template < class X, class Y >
1911  FastDelegate(Y * pthis, 
1912    R (X::* function_to_bind)(  ))
1913    : BaseType(pthis, function_to_bind)  { }
1914
1915  template < class X, class Y >
1916  FastDelegate(const Y *pthis,
1917      R (X::* function_to_bind)(  ) const)
1918    : BaseType(pthis, function_to_bind)
1919  {  }
1920
1921  FastDelegate(R (*function_to_bind)(  ))
1922    : BaseType(function_to_bind)  { }
1923  void operator = (const BaseType &x)  {    
1924      *static_cast<BaseType*>(this) = x; }
1925};
1926
1927//N=1
1928// Specialization to allow use of
1929// FastDelegate< R ( Param1 ) >
1930// instead of 
1931// FastDelegate1 < Param1, R >
1932template<typename R, class Param1>
1933class FastDelegate< R ( Param1 ) >
1934  // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
1935  : public FastDelegate1 < Param1, R >
1936{
1937public:
1938  // Make using the base type a bit easier via typedef.
1939  typedef FastDelegate1 < Param1, R> BaseType;
1940
1941  // Allow users access to the specific type of this delegate.
1942  typedef FastDelegate SelfType;
1943
1944  // Mimic the base class constructors.
1945  FastDelegate() : BaseType() { }
1946
1947  template < class X, class Y >
1948  FastDelegate(Y * pthis, 
1949    R (X::* function_to_bind)( Param1 p1 ))
1950    : BaseType(pthis, function_to_bind)  { }
1951
1952  template < class X, class Y >
1953  FastDelegate(const Y *pthis,
1954      R (X::* function_to_bind)( Param1 p1 ) const)
1955    : BaseType(pthis, function_to_bind)
1956  {  }
1957
1958  FastDelegate(R (*function_to_bind)( Param1 p1 ))
1959    : BaseType(function_to_bind)  { }
1960  void operator = (const BaseType &x)  {    
1961      *static_cast<BaseType*>(this) = x; }
1962};
1963
1964//N=2
1965// Specialization to allow use of
1966// FastDelegate< R ( Param1, Param2 ) >
1967// instead of 
1968// FastDelegate2 < Param1, Param2, R >
1969template<typename R, class Param1, class Param2>
1970class FastDelegate< R ( Param1, Param2 ) >
1971  // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
1972  : public FastDelegate2 < Param1, Param2, R >
1973{
1974public:
1975  // Make using the base type a bit easier via typedef.
1976  typedef FastDelegate2 < Param1, Param2, R> BaseType;
1977
1978  // Allow users access to the specific type of this delegate.
1979  typedef FastDelegate SelfType;
1980
1981  // Mimic the base class constructors.
1982  FastDelegate() : BaseType() { }
1983
1984  template < class X, class Y >
1985  FastDelegate(Y * pthis, 
1986    R (X::* function_to_bind)( Param1 p1, Param2 p2 ))
1987    : BaseType(pthis, function_to_bind)  { }
1988
1989  template < class X, class Y >
1990  FastDelegate(const Y *pthis,
1991      R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const)
1992    : BaseType(pthis, function_to_bind)
1993  {  }
1994
1995  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 ))
1996    : BaseType(function_to_bind)  { }
1997  void operator = (const BaseType &x)  {    
1998      *static_cast<BaseType*>(this) = x; }
1999};
2000
2001//N=3
2002// Specialization to allow use of
2003// FastDelegate< R ( Param1, Param2, Param3 ) >
2004// instead of 
2005// FastDelegate3 < Param1, Param2, Param3, R >
2006template<typename R, class Param1, class Param2, class Param3>
2007class FastDelegate< R ( Param1, Param2, Param3 ) >
2008  // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
2009  : public FastDelegate3 < Param1, Param2, Param3, R >
2010{
2011public:
2012  // Make using the base type a bit easier via typedef.
2013  typedef FastDelegate3 < Param1, Param2, Param3, R> BaseType;
2014
2015  // Allow users access to the specific type of this delegate.
2016  typedef FastDelegate SelfType;
2017
2018  // Mimic the base class constructors.
2019  FastDelegate() : BaseType() { }
2020
2021  template < class X, class Y >
2022  FastDelegate(Y * pthis, 
2023    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
2024    : BaseType(pthis, function_to_bind)  { }
2025
2026  template < class X, class Y >
2027  FastDelegate(const Y *pthis,
2028      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const)
2029    : BaseType(pthis, function_to_bind)
2030  {  }
2031
2032  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
2033    : BaseType(function_to_bind)  { }
2034  void operator = (const BaseType &x)  {    
2035      *static_cast<BaseType*>(this) = x; }
2036};
2037
2038//N=4
2039// Specialization to allow use of
2040// FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
2041// instead of 
2042// FastDelegate4 < Param1, Param2, Param3, Param4, R >
2043template<typename R, class Param1, class Param2, class Param3, class Param4>
2044class FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
2045  // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
2046  : public FastDelegate4 < Param1, Param2, Param3, Param4, R >
2047{
2048public:
2049  // Make using the base type a bit easier via typedef.
2050  typedef FastDelegate4 < Param1, Param2, Param3, Param4, R> BaseType;
2051
2052  // Allow users access to the specific type of this delegate.
2053  typedef FastDelegate SelfType;
2054
2055  // Mimic the base class constructors.
2056  FastDelegate() : BaseType() { }
2057
2058  template < class X, class Y >
2059  FastDelegate(Y * pthis, 
2060    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
2061    : BaseType(pthis, function_to_bind)  { }
2062
2063  template < class X, class Y >
2064  FastDelegate(const Y *pthis,
2065      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const)
2066    : BaseType(pthis, function_to_bind)
2067  {  }
2068
2069  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
2070    : BaseType(function_to_bind)  { }
2071  void operator = (const BaseType &x)  {    
2072      *static_cast<BaseType*>(this) = x; }
2073};
2074
2075//N=5
2076// Specialization to allow use of
2077// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
2078// instead of 
2079// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
2080template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
2081class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
2082  // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
2083  : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
2084{
2085public:
2086  // Make using the base type a bit easier via typedef.
2087  typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R> BaseType;
2088
2089  // Allow users access to the specific type of this delegate.
2090  typedef FastDelegate SelfType;
2091
2092  // Mimic the base class constructors.
2093  FastDelegate() : BaseType() { }
2094
2095  template < class X, class Y >
2096  FastDelegate(Y * pthis, 
2097    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
2098    : BaseType(pthis, function_to_bind)  { }
2099
2100  template < class X, class Y >
2101  FastDelegate(const Y *pthis,
2102      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const)
2103    : BaseType(pthis, function_to_bind)
2104  {  }
2105
2106  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
2107    : BaseType(function_to_bind)  { }
2108  void operator = (const BaseType &x)  {    
2109      *static_cast<BaseType*>(this) = x; }
2110};
2111
2112//N=6
2113// Specialization to allow use of
2114// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
2115// instead of 
2116// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
2117template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
2118class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
2119  // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
2120  : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
2121{
2122public:
2123  // Make using the base type a bit easier via typedef.
2124  typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R> BaseType;
2125
2126  // Allow users access to the specific type of this delegate.
2127  typedef FastDelegate SelfType;
2128
2129  // Mimic the base class constructors.
2130  FastDelegate() : BaseType() { }
2131
2132  template < class X, class Y >
2133  FastDelegate(Y * pthis, 
2134    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
2135    : BaseType(pthis, function_to_bind)  { }
2136
2137  template < class X, class Y >
2138  FastDelegate(const Y *pthis,
2139      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const)
2140    : BaseType(pthis, function_to_bind)
2141  {  }
2142
2143  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
2144    : BaseType(function_to_bind)  { }
2145  void operator = (const BaseType &x)  {    
2146      *static_cast<BaseType*>(this) = x; }
2147};
2148
2149//N=7
2150// Specialization to allow use of
2151// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
2152// instead of 
2153// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
2154template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
2155class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
2156  // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
2157  : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
2158{
2159public:
2160  // Make using the base type a bit easier via typedef.
2161  typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R> BaseType;
2162
2163  // Allow users access to the specific type of this delegate.
2164  typedef FastDelegate SelfType;
2165
2166  // Mimic the base class constructors.
2167  FastDelegate() : BaseType() { }
2168
2169  template < class X, class Y >
2170  FastDelegate(Y * pthis, 
2171    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
2172    : BaseType(pthis, function_to_bind)  { }
2173
2174  template < class X, class Y >
2175  FastDelegate(const Y *pthis,
2176      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const)
2177    : BaseType(pthis, function_to_bind)
2178  {  }
2179
2180  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
2181    : BaseType(function_to_bind)  { }
2182  void operator = (const BaseType &x)  {    
2183      *static_cast<BaseType*>(this) = x; }
2184};
2185
2186//N=8
2187// Specialization to allow use of
2188// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
2189// instead of 
2190// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
2191template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
2192class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
2193  // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
2194  : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
2195{
2196public:
2197  // Make using the base type a bit easier via typedef.
2198  typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R> BaseType;
2199
2200  // Allow users access to the specific type of this delegate.
2201  typedef FastDelegate SelfType;
2202
2203  // Mimic the base class constructors.
2204  FastDelegate() : BaseType() { }
2205
2206  template < class X, class Y >
2207  FastDelegate(Y * pthis, 
2208    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
2209    : BaseType(pthis, function_to_bind)  { }
2210
2211  template < class X, class Y >
2212  FastDelegate(const Y *pthis,
2213      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const)
2214    : BaseType(pthis, function_to_bind)
2215  {  }
2216
2217  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
2218    : BaseType(function_to_bind)  { }
2219  void operator = (const BaseType &x)  {    
2220      *static_cast<BaseType*>(this) = x; }
2221};
2222
2223//N=11
2224// Specialization to allow use of
2225// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) >
2226// instead of 
2227// FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R >
2228template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
2229class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) >
2230  // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11
2231  : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R >
2232{
2233public:
2234  // Make using the base type a bit easier via typedef.
2235  typedef FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R> BaseType;
2236
2237  // Allow users access to the specific type of this delegate.
2238  typedef FastDelegate SelfType;
2239
2240  // Mimic the base class constructors.
2241  FastDelegate() : BaseType() { }
2242
2243  template < class X, class Y >
2244  FastDelegate(Y * pthis, 
2245    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ))
2246    : BaseType(pthis, function_to_bind)  { }
2247
2248  template < class X, class Y >
2249  FastDelegate(const Y *pthis,
2250      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ) const)
2251    : BaseType(pthis, function_to_bind)
2252  {  }
2253
2254  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ))
2255    : BaseType(function_to_bind)  { }
2256  void operator = (const BaseType &x)  {    
2257      *static_cast<BaseType*>(this) = x; }
2258};
2259
2260//N=12
2261// Specialization to allow use of
2262// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) >
2263// instead of 
2264// FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R >
2265template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
2266class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) >
2267  // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12
2268  : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R >
2269{
2270public:
2271  // Make using the base type a bit easier via typedef.
2272  typedef FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R> BaseType;
2273
2274  // Allow users access to the specific type of this delegate.
2275  typedef FastDelegate SelfType;
2276
2277  // Mimic the base class constructors.
2278  FastDelegate() : BaseType() { }
2279
2280  template < class X, class Y >
2281  FastDelegate(Y * pthis, 
2282    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ))
2283    : BaseType(pthis, function_to_bind)  { }
2284
2285  template < class X, class Y >
2286  FastDelegate(const Y *pthis,
2287      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ) const)
2288    : BaseType(pthis, function_to_bind)
2289  {  }
2290
2291  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ))
2292    : BaseType(function_to_bind)  { }
2293  void operator = (const BaseType &x)  {    
2294      *static_cast<BaseType*>(this) = x; }
2295};
2296
2297//N=13
2298// Specialization to allow use of
2299// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) >
2300// instead of 
2301// FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R >
2302template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
2303class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) >
2304  // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13
2305  : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R >
2306{
2307public:
2308  // Make using the base type a bit easier via typedef.
2309  typedef FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R> BaseType;
2310
2311  // Allow users access to the specific type of this delegate.
2312  typedef FastDelegate SelfType;
2313
2314  // Mimic the base class constructors.
2315  FastDelegate() : BaseType() { }
2316
2317  template < class X, class Y >
2318  FastDelegate(Y * pthis, 
2319    R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ))
2320    : BaseType(pthis, function_to_bind)  { }
2321
2322  template < class X, class Y >
2323  FastDelegate(const Y *pthis,
2324      R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ) const)
2325    : BaseType(pthis, function_to_bind)
2326  {  }
2327
2328  FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ))
2329    : BaseType(function_to_bind)  { }
2330  void operator = (const BaseType &x)  {    
2331      *static_cast<BaseType*>(this) = x; }
2332};
2333
2334
2335#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
2336
2337////////////////////////////////////////////////////////////////////////////////
2338//                Fast Delegates, part 5:
2339//
2340//          MakeDelegate() helper function
2341//
2342//       MakeDelegate(&x, &X::func) returns a fastdelegate of the type
2343//       necessary for calling x.func() with the correct number of arguments.
2344//       This makes it possible to eliminate many typedefs from user code.
2345//
2346////////////////////////////////////////////////////////////////////////////////
2347
2348// Also declare overloads of a MakeDelegate() global function to 
2349// reduce the need for typedefs.
2350// We need seperate overloads for const and non-const member functions.
2351// Also, because of the weird rule about the class of derived member function pointers,
2352// implicit downcasts may need to be applied later to the 'this' pointer.
2353// That's why two classes (X and Y) appear in the definitions. Y must be implicitly
2354// castable to X.
2355
2356// Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
2357// GCC 3.2 and later won't compile this unless it's preceded by 'typename',
2358// but VC6 doesn't allow 'typename' in this context.
2359// So, I have to use a macro.
2360
2361#ifdef FASTDLGT_VC6
2362#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
2363#else 
2364#define FASTDLGT_RETTYPE RetType
2365#endif
2366
2367//N=0
2368template <class X, class Y, class RetType>
2369FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)()) { 
2370   return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
2371}
2372
2373template <class X, class Y, class RetType>
2374FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)() const) { 
2375   return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
2376}
2377
2378//N=1
2379template <class X, class Y, class Param1, class RetType>
2380FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { 
2381   return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
2382}
2383
2384template <class X, class Y, class Param1, class RetType>
2385FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { 
2386   return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
2387}
2388
2389//N=2
2390template <class X, class Y, class Param1, class Param2, class RetType>
2391FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { 
2392   return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
2393}
2394
2395template <class X, class Y, class Param1, class Param2, class RetType>
2396FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { 
2397   return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
2398}
2399
2400//N=3
2401template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
2402FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { 
2403   return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
2404}
2405
2406template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
2407FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { 
2408   return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
2409}
2410
2411//N=4
2412template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
2413FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { 
2414   return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
2415}
2416
2417template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
2418FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { 
2419   return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
2420}
2421
2422//N=5
2423template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
2424FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { 
2425   return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
2426}
2427
2428template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
2429FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { 
2430   return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
2431}
2432
2433//N=6
2434template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
2435FastDelegate6<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)) { 
2436   return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
2437}
2438
2439template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
2440FastDelegate6<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) { 
2441   return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
2442}
2443
2444//N=7
2445template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
2446FastDelegate7<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)) { 
2447   return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
2448}
2449
2450template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
2451FastDelegate7<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) { 
2452   return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
2453}
2454
2455//N=8
2456template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
2457FastDelegate8<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)) { 
2458   return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
2459}
2460
2461template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
2462FastDelegate8<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) { 
2463   return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
2464}
2465
2466//N=11
2467template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class RetType>
2468FastDelegate11<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { 
2469   return FastDelegate11<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, FASTDLGT_RETTYPE>(x, func);
2470}
2471
2472template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class RetType>
2473FastDelegate11<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { 
2474   return FastDelegate11<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, FASTDLGT_RETTYPE>(x, func);
2475}
2476
2477//N=12
2478template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class RetType>
2479FastDelegate12<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { 
2480   return FastDelegate12<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, FASTDLGT_RETTYPE>(x, func);
2481}
2482
2483template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class RetType>
2484FastDelegate12<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { 
2485   return FastDelegate12<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, FASTDLGT_RETTYPE>(x, func);
2486}
2487
2488//N=13
2489template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class RetType>
2490FastDelegate13<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { 
2491   return FastDelegate13<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, FASTDLGT_RETTYPE>(x, func);
2492}
2493
2494template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class RetType>
2495FastDelegate13<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { 
2496   return FastDelegate13<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, FASTDLGT_RETTYPE>(x, func);
2497}
2498
2499
2500 // clean up after ourselves...
2501#undef FASTDLGT_RETTYPE
2502
2503} // namespace fastdelegate
2504
2505#endif // !defined(FASTDELEGATE_H)
2506
2507