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


socketcan_interface
Author(s): Mathias Lüdtke
autogenerated on Fri May 14 2021 02:59:39