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