delegate.h

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

 
Support This Project
SourceForge.net Logo