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