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