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