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