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