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