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