avr/cpp/common/Delegate.h

Go to the documentation of this file.
00001 //
00002 //      Efficient delegates in C++ that generate only two lines of asm code!
00003 //  Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
00004 //
00005 //                                              - Don Clugston, Mar 2004.
00006 //              Major contributions were made by Jody Hagins.
00007 //
00008 //
00009 //              Adapted for WinAVR by Lauri Kirikal, Mar 2007.
00010 //
00011 // History:
00012 // 24-Apr-04 1.0  * Submitted to CodeProject. 
00013 // 28-Apr-04 1.1  * Prevent most unsafe uses of evil static function hack.
00014 //                                * Improved syntax for horrible_cast (thanks Paul Bludov).
00015 //                                * Tested on Metrowerks MWCC and Intel ICL (IA32)
00016 //                                * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
00017 //      27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
00018 //                                * Now works on /clr "managed C++" code on VC7, VC7.1
00019 //                                * Comeau C++ now compiles without warnings.
00020 //                                * Prevent the virtual inheritance case from being used on 
00021 //                                        VC6 and earlier, which generate incorrect code.
00022 //                                * Improved warning and error messages. Non-standard hacks
00023 //                                       now have compile-time checks to make them safer.
00024 //                                * implicit_cast used instead of static_cast in many cases.
00025 //                                * If calling a const member function, a const class pointer can be used.
00026 //                                * MakeDelegate() global helper function added to simplify pass-by-value.
00027 //                                * Added fastdelegate.Clear()
00028 // 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)
00029 // 30-Oct-04 1.3  * Support for (non-void) return values.
00030 //                                * No more workarounds in client code!
00031 //                                       MSVC and Intel now use a clever hack invented by John Dlugosz:
00032 //                                   - The FASTDELEGATEDECLARE workaround is no longer necessary.
00033 //                                       - No more warning messages for VC6
00034 //                                * Less use of macros. Error messages should be more comprehensible.
00035 //                                * Added include guards
00036 //                                * Added FastDelegate::Empty() to test if invocation is safe (Thanks Neville Franks).
00037 //                                * Now tested on VS 2005 Express Beta, PGI C++
00038 // 24-Dec-04 1.4  * Added DelegateMemento, to allow collections of disparate delegates.
00039 //                * <,>,<=,>= comparison operators to allow storage in ordered containers.
00040 //                                * Substantial reduction of code size, especially the 'Closure' class.
00041 //                                * Standardised all the compiler-specific workarounds.
00042 //                * MFP conversion now works for CodePlay (but not yet supported in the full code).
00043 //                * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
00044 //                                * New syntax: FastDelegate< int (char *, double) >. 
00045 // 14-Feb-05 1.4.1* Now treats =0 as equivalent to .Clear(), ==0 as equivalent to .Empty(). (Thanks elfric).
00046 //                                * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.
00047 // 30-Mar-05 1.5  * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.Empty())"
00048 //                                * Fully supported by CodePlay VectorC
00049 //                * Bugfix for Metrowerks: Empty() was buggy because a valid MFP can be 0 on MWCC!
00050 //                * More optimal assignment,== and != operators for static function pointers.
00051 
00052 /*
00053         Minor Changes For AVR C++ Lib Compatibility
00054         
00055         STARTS ...
00056 */
00057 #ifndef __AVR_CPP_DELEGATE_H__
00058 #define __AVR_CPP_DELEGATE_H__
00059 
00060 #if !(defined(EXCLUDE_FAST_DELEGATE) && defined(EXCLUDE_MULTI_DELEGATE) && defined(EXLUDE_DATA_DELEGATE))
00061 
00062 #ifndef __cplusplus
00063 #error "Delegate.h needs C++ compiler."
00064 #else
00065 
00066 /*
00067         Header file memory.h is missing in WinAVR.
00068         Needed functions are defined in string.h
00069         
00070         Lauri Kirikal
00071 */
00072 #ifdef __AVR__
00073 #include <string.h>
00074 #else
00075 #include <memory.h> // to allow <,> comparisons
00076 #endif
00077 
00078 /* 
00079         ... ENDS
00080 
00081         Lauri Kirikal
00082 */
00083 
00085 //                                              Configuration options
00086 //
00088 
00089 // Uncomment the following #define for optimally-sized delegates.
00090 // In this case, the generated asm code is almost identical to the code you'd get
00091 // if the compiler had native support for delegates.
00092 // It will not work on systems where sizeof(dataptr) < sizeof(codeptr). 
00093 // Thus, it will not work for DOS compilers using the medium model.
00094 // It will also probably fail on some DSP systems.
00095 #define FASTDELEGATE_USESTATICFUNCTIONHACK
00096 
00097 // Uncomment the next line to allow function declarator syntax.
00098 // It is automatically enabled for those compilers where it is known to work.
00099 //#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00100 
00102 //                                              Compiler identification for workarounds
00103 //
00105 
00106 // Compiler identification. It's not easy to identify Visual C++ because
00107 // many vendors fraudulently define Microsoft's identifiers.
00108 #if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)
00109 #define FASTDLGT_ISMSVC
00110 
00111 #if (_MSC_VER <1300) // Many workarounds are required for VC6.
00112 #define FASTDLGT_VC6
00113 #pragma warning(disable:4786) // disable this ridiculous warning
00114 #endif
00115 
00116 #endif
00117 
00118 // Does the compiler uses Microsoft's member function pointer structure?
00119 // If so, it needs special treatment.
00120 // Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's 
00121 // identifier, _MSC_VER. We need to filter Metrowerks out.
00122 #if defined(_MSC_VER) && !defined(__MWERKS__)
00123 #define FASTDLGT_MICROSOFT_MFP
00124 
00125 #if !defined(__VECTOR_C)
00126 // CodePlay doesn't have the __single/multi/virtual_inheritance keywords
00127 #define FASTDLGT_HASINHERITANCE_KEYWORDS
00128 #endif
00129 #endif
00130 
00131 // Does it allow function declarator syntax? The following compilers are known to work:
00132 #if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1
00133 #define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00134 #endif
00135 
00136 // Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.
00137 #if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)
00138 #define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00139 #endif
00140 
00141 // It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
00142 #if defined (__MWERKS__)
00143 #define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
00144 #endif
00145 
00146 #ifdef __GNUC__ // Workaround GCC bug #8271 
00147         // At present, GCC doesn't recognize constness of MFPs in templates
00148 #define FASTDELEGATE_GCC_BUG_8271
00149 #endif
00150 
00151 
00152 
00154 //                                              General tricks used in this code
00155 //
00156 // (a) Error messages are generated by typdefing an array of negative size to
00157 //     generate compile-time errors.
00158 // (b) Warning messages on MSVC are generated by declaring unused variables, and
00159 //          enabling the "variable XXX is never used" warning.
00160 // (c) Unions are used in a few compiler-specific cases to perform illegal casts.
00161 // (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
00162 //     (char *) first to ensure that the correct number of *bytes* are added.
00163 //
00165 //                                              Helper templates
00166 //
00168 
00169 /*
00170         namespace names modified:
00171                 fastdelegate -> CppDelegate
00172                 detail -> Internal
00173         
00174         Lauri Kirikal
00175 */
00176 
00177 namespace CppDelegate {
00178 namespace Internal {    // we'll hide the implementation details in a nested namespace.
00179 
00180 //              implicit_cast< >
00181 // I believe this was originally going to be in the C++ standard but 
00182 // was left out by accident. It's even milder than static_cast.
00183 // I use it instead of static_cast<> to emphasize that I'm not doing
00184 // anything nasty. 
00185 // Usage is identical to static_cast<>
00186 template <class OutputClass, class InputClass>
00187 inline OutputClass implicit_cast(InputClass input){
00188         return input;
00189 }
00190 
00191 //              horrible_cast< >
00192 // This is truly evil. It completely subverts C++'s type system, allowing you 
00193 // to cast from any class to any other class. Technically, using a union 
00194 // to perform the cast is undefined behaviour (even in C). But we can see if
00195 // it is OK by checking that the union is the same size as each of its members.
00196 // horrible_cast<> should only be used for compiler-specific workarounds. 
00197 // Usage is identical to reinterpret_cast<>.
00198 
00199 // This union is declared outside the horrible_cast because BCC 5.5.1
00200 // can't inline a function with a nested class, and gives a warning.
00201 template <class OutputClass, class InputClass>
00202 union horrible_union{
00203         OutputClass out;
00204         InputClass in;
00205 };
00206 
00207 template <class OutputClass, class InputClass>
00208 inline OutputClass horrible_cast(const InputClass input){
00209         horrible_union<OutputClass, InputClass> u;
00210         // Cause a compile-time error if in, out and u are not the same size.
00211         // If the compile fails here, it means the compiler has peculiar
00212         // unions which would prevent the cast from working.
00213         typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) 
00214                 && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
00215         u.in = input;
00216         return u.out;
00217 }
00218 
00220 //                                              Workarounds
00221 //
00223 
00224 // Backwards compatibility: This macro used to be necessary in the virtual inheritance
00225 // case for Intel and Microsoft. Now it just forward-declares the class.
00226 #define FASTDELEGATEDECLARE(CLASSNAME)  class CLASSNAME;
00227 
00228 // Prevent use of the static function hack with the DOS medium model.
00229 #ifdef __MEDIUM__
00230 #undef FASTDELEGATE_USESTATICFUNCTIONHACK
00231 #endif
00232 
00233 //                      DefaultVoid - a workaround for 'void' templates in VC6.
00234 //
00235 //  (1) VC6 and earlier do not allow 'void' as a default template argument.
00236 //  (2) They also doesn't allow you to return 'void' from a function.
00237 //
00238 // Workaround for (1): Declare a dummy type 'DefaultVoid' which we use
00239 //   when we'd like to use 'void'. We convert it into 'void' and back
00240 //   using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
00241 // Workaround for (2): On VC6, the code for calling a void function is
00242 //   identical to the code for calling a non-void function in which the
00243 //   return value is never used, provided the return value is returned
00244 //   in the EAX register, rather than on the stack. 
00245 //   This is true for most fundamental types such as int, enum, void *.
00246 //   Const void * is the safest option since it doesn't participate 
00247 //   in any automatic conversions. But on a 16-bit compiler it might
00248 //   cause extra code to be generated, so we disable it for all compilers
00249 //   except for VC6 (and VC5).
00250 #ifdef FASTDLGT_VC6
00251 // VC6 workaround
00252 typedef const void * DefaultVoid;
00253 #else
00254 // On any other compiler, just use a normal void.
00255 typedef void DefaultVoid;
00256 #endif
00257 
00258 // Translate from 'DefaultVoid' to 'void'.
00259 // Everything else is unchanged
00260 template <class T>
00261 struct DefaultVoidToVoid { typedef T type; };
00262 
00263 template <>
00264 struct DefaultVoidToVoid<DefaultVoid> { typedef void type; };
00265 
00266 // Translate from 'void' into 'DefaultVoid'
00267 // Everything else is unchanged
00268 template <class T>
00269 struct VoidToDefaultVoid { typedef T type; };
00270 
00271 template <>
00272 struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
00273 
00274 
00275 
00277 //                                              Fast Delegates, part 1:
00278 //
00279 //              Conversion of member function pointer to a standard form
00280 //
00282 
00283 // GenericClass is a fake class, ONLY used to provide a type.
00284 // It is vitally important that it is never defined, so that the compiler doesn't
00285 // think it can optimize the invocation. For example, Borland generates simpler
00286 // code if it knows the class only uses single inheritance.
00287 
00288 // Compilers using Microsoft's structure need to be treated as a special case.
00289 #ifdef  FASTDLGT_MICROSOFT_MFP
00290 
00291 #ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
00292         // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP 
00293         // (4 bytes), even when the /vmg option is used. Declaring an empty class 
00294         // would give 16 byte pointers in this case....
00295         class __single_inheritance GenericClass;
00296 #endif
00297         // ...but for Codeplay, an empty class *always* gives 4 byte pointers.
00298         // If compiled with the /clr option ("managed C++"), the JIT compiler thinks
00299         // it needs to load GenericClass before it can call any of its functions,
00300         // (compiles OK but crashes at runtime!), so we need to declare an 
00301         // empty class to make it happy.
00302         // Codeplay and VC4 can't cope with the unknown_inheritance case either.
00303         class GenericClass {};
00304 #else
00305         class GenericClass;
00306 #endif
00307 
00308 // The size of a single inheritance member function pointer.
00309 const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());
00310 
00311 //                                              SimplifyMemFunc< >::Convert()
00312 //
00313 //      A template function that converts an arbitrary member function pointer into the 
00314 //      simplest possible form of member function pointer, using a supplied 'this' pointer.
00315 //  According to the standard, this can be done legally with reinterpret_cast<>.
00316 //      For (non-standard) compilers which use member function pointers which vary in size 
00317 //  depending on the class, we need to use      knowledge of the internal structure of a 
00318 //  member function pointer, as used by the compiler. Template specialization is used
00319 //  to distinguish between the sizes. Because some compilers don't support partial 
00320 //      template specialisation, I use full specialisation of a wrapper struct.
00321 
00322 // general case -- don't know how to convert it. Force a compile failure
00323 template <int N>
00324 struct SimplifyMemFunc {
00325         template <class X, class XFuncType, class GenericMemFuncType>
00326         inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00327                 GenericMemFuncType &bound_func) { 
00328                 // Unsupported member function type -- force a compile failure.
00329             // (it's illegal to have a array with negative size).
00330                 typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
00331                 return 0; 
00332         }
00333 };
00334 
00335 // For compilers where all member func ptrs are the same size, everything goes here.
00336 // For non-standard compilers, only single_inheritance classes go here.
00337 template <>
00338 struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE>  {       
00339         template <class X, class XFuncType, class GenericMemFuncType>
00340         inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, 
00341                         GenericMemFuncType &bound_func) {
00342 #if defined __DMC__  
00343                 // Digital Mars doesn't allow you to cast between abitrary PMF's, 
00344                 // even though the standard says you can. The 32-bit compiler lets you
00345                 // static_cast through an int, but the DOS compiler doesn't.
00346                 bound_func = horrible_cast<GenericMemFuncType>(function_to_bind);
00347 #else 
00348         bound_func = reinterpret_cast<GenericMemFuncType>(function_to_bind);
00349 #endif
00350         return reinterpret_cast<GenericClass *>(pthis);
00351         }
00352 };
00353 
00355 //                                              Fast Delegates, part 1b:
00356 //
00357 //                                      Workarounds for Microsoft and Intel
00358 //
00360 
00361 
00362 // Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
00363 // need to be treated as a special case.
00364 #ifdef FASTDLGT_MICROSOFT_MFP
00365 
00366 /*
00367         ... ERASED for shorter compiling time ...
00368 
00369         Lauri Kirikal
00370 */
00371 
00372 #error "MSVC, Intel, Codeplay compilers support erased from this file."
00373 
00374 #endif // MS/Intel hacks
00375 
00376 }  // namespace Internal
00377 
00379 //                                              Fast Delegates, part 2:
00380 //
00381 //      Define the delegate storage, and cope with static functions
00382 //
00384 
00385 // DelegateMemento -- an opaque structure which can hold an arbitary delegate.
00386 // It knows nothing about the calling convention or number of arguments used by
00387 // the function pointed to.
00388 // It supplies comparison operators so that it can be stored in STL collections.
00389 // It cannot be set to anything other than null, nor invoked directly: 
00390 //   it must be converted to a specific delegate.
00391 
00392 // Implementation:
00393 // There are two possible implementations: the Safe method and the Evil method.
00394 //                              DelegateMemento - Safe version
00395 //
00396 // This implementation is standard-compliant, but a bit tricky.
00397 // A static function pointer is stored inside the class. 
00398 // Here are the valid values:
00399 // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
00400 // |   0                                |  0       |   0        | Empty          |
00401 // |   !=0              |(dontcare)|  Invoker   | Static function|
00402 // |   0                |  !=0     |  !=0*      | Method call    |
00403 // +--------------------+----------+------------+----------------+
00404 //  * For Metrowerks, this can be 0. (first virtual function in a 
00405 //       single_inheritance class).
00406 // When stored stored inside a specific delegate, the 'dontcare' entries are replaced
00407 // with a reference to the delegate itself. This complicates the = and == operators
00408 // for the delegate class.
00409 
00410 //                              DelegateMemento - Evil version
00411 //
00412 // For compilers where data pointers are at least as big as code pointers, it is 
00413 // possible to store the function pointer in the this pointer, using another 
00414 // horrible_cast. In this case the DelegateMemento implementation is simple:
00415 // +--pThis --+-- pMemFunc-+-- Meaning---------------------+
00416 // |    0     |  0         | Empty                         |
00417 // |  !=0     |  !=0*      | Static function or method call|
00418 // +----------+------------+-------------------------------+
00419 //  * For Metrowerks, this can be 0. (first virtual function in a 
00420 //       single_inheritance class).
00421 // Note that the Sun C++ and MSVC documentation explicitly state that they 
00422 // support static_cast between void * and function pointers.
00423 
00424 /*
00425         DelegateMemento moved from CppDelegate namespace to CppDelegate::Internal namespace
00426         
00427         Lauri Kirikal
00428 */
00429 namespace Internal
00430 {
00431 class DelegateMemento {
00432 protected: 
00433         // the data is protected, not private, because many
00434         // compilers have problems with template friends.
00435         typedef void (Internal::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.
00436         Internal::GenericClass *m_pthis;
00437         GenericMemFuncType m_pFunction;
00438 
00439 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00440         typedef void (*GenericFuncPtr)(); // arbitrary code pointer
00441         GenericFuncPtr m_pStaticFunction;
00442 #endif
00443 
00444 public:
00445 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00446         DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
00447         void Clear() {
00448                 m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
00449         }
00450 #else
00451         DelegateMemento() : m_pthis(0), m_pFunction(0) {};
00452         void Clear() {  m_pthis=0; m_pFunction=0;       }
00453 #endif
00454 public:
00455 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00456         inline bool IsEqual (const DelegateMemento &x) const{
00457             // We have to cope with the static function pointers as a special case
00458                 if (m_pFunction!=x.m_pFunction) return false;
00459                 // the static function ptrs must either both be equal, or both be 0.
00460                 if (m_pStaticFunction!=x.m_pStaticFunction) return false;
00461                 if (m_pStaticFunction!=0) return m_pthis==x.m_pthis;
00462                 else return true;
00463         }
00464 #else // Evil Method
00465         inline bool IsEqual (const DelegateMemento &x) const{
00466                 return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
00467         }
00468 #endif
00469         // Provide a strict weak ordering for DelegateMementos.
00470         inline bool IsLess(const DelegateMemento &right) const {
00471                 // deal with static function pointers first
00472 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00473                 if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) 
00474                                 return m_pStaticFunction < right.m_pStaticFunction;
00475 #endif
00476                 if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis;
00477         // There are no ordering operators for member function pointers, 
00478         // but we can fake one by comparing each byte. The resulting ordering is
00479         // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
00480                 return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
00481 
00482         }
00483         // BUGFIX (Mar 2005):
00484         // We can't just compare m_pFunction because on Metrowerks,
00485         // m_pFunction can be zero even if the delegate is not empty!
00486         inline bool operator ! () const         // Is it bound to anything?
00487         { return m_pthis==0 && m_pFunction==0; }
00488         inline bool Empty() const               // Is it bound to anything?
00489         { return m_pthis==0 && m_pFunction==0; }
00490 public:
00491         DelegateMemento & operator = (const DelegateMemento &right)  {
00492                 SetMementoFrom(right); 
00493                 return *this;
00494         }
00495         inline bool operator <(const DelegateMemento &right) {
00496                 return IsLess(right);
00497         }
00498         inline bool operator >(const DelegateMemento &right) {
00499                 return right.IsLess(*this);
00500         }
00501         DelegateMemento (const DelegateMemento &right)  : 
00502                 m_pthis(right.m_pthis), m_pFunction(right.m_pFunction)
00503 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00504                 , m_pStaticFunction (right.m_pStaticFunction)
00505 #endif
00506                 {}
00507 protected:
00508         void SetMementoFrom(const DelegateMemento &right)  {
00509                 m_pFunction = right.m_pFunction;
00510                 m_pthis = right.m_pthis;
00511 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00512                 m_pStaticFunction = right.m_pStaticFunction;
00513 #endif
00514         }
00515 };
00516 } // namespace Internal
00517 
00518 //                                              ClosurePtr<>
00519 //
00520 // A private wrapper class that adds function signatures to DelegateMemento.
00521 // It's the class that does most of the actual work.
00522 // The signatures are specified by:
00523 // GenericMemFunc: must be a type of GenericClass member function pointer. 
00524 // StaticFuncPtr:  must be a type of function pointer with the same signature 
00525 //                 as GenericMemFunc.
00526 // UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
00527 //                 where it never returns void (returns DefaultVoid instead).
00528 
00529 // An outer class, FastDelegateN<>, handles the invoking and creates the
00530 // necessary typedefs.
00531 // This class does everything else.
00532 
00533 namespace Internal {
00534 
00535 template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
00536 class ClosurePtr : public DelegateMemento {
00537 public:
00538         // These functions are for setting the delegate to a member function.
00539 
00540         // Here's the clever bit: we convert an arbitrary member function into a 
00541         // standard form. XMemFunc should be a member function of class X, but I can't 
00542         // enforce that here. It needs to be enforced by the wrapper class.
00543         template < class X, class XMemFunc >
00544         inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) {
00545                 m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
00546                         ::Convert(pthis, function_to_bind, m_pFunction);
00547 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00548                 m_pStaticFunction = 0;
00549 #endif
00550         }
00551         // For const member functions, we only need a const class pointer.
00552         // Since we know that the member function is const, it's safe to 
00553         // remove the const qualifier from the 'this' pointer with a const_cast.
00554         // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
00555         template < class X, class XMemFunc>
00556         inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) {
00557                 m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
00558                         ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
00559 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00560                 m_pStaticFunction = 0;
00561 #endif
00562         }
00563 #ifdef FASTDELEGATE_GCC_BUG_8271        // At present, GCC doesn't recognize constness of MFPs in templates
00564         template < class X, class XMemFunc>
00565         inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) {
00566                 bindconstmemfunc(pthis, function_to_bind);
00567 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00568                 m_pStaticFunction = 0;
00569 #endif
00570         }
00571 #endif
00572         // These functions are required for invoking the stored function
00573         inline GenericClass *GetClosureThis() const { return m_pthis; }
00574         inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
00575 
00576 // There are a few ways of dealing with static function pointers.
00577 // There's a standard-compliant, but tricky method.
00578 // There's also a straightforward hack, that won't work on DOS compilers using the
00579 // medium memory model. It's so evil that I can't recommend it, but I've
00580 // implemented it anyway because it produces very nice asm code.
00581 
00582 #if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00583 
00584 //                              ClosurePtr<> - Safe version
00585 //
00586 // This implementation is standard-compliant, but a bit tricky.
00587 // I store the function pointer inside the class, and the delegate then
00588 // points to itself. Whenever the delegate is copied, these self-references
00589 // must be transformed, and this complicates the = and == operators.
00590 public:
00591         // The next two functions are for operator ==, =, and the copy constructor.
00592         // We may need to convert the m_pthis pointers, so that
00593         // they remain as self-references.
00594         template< class DerivedClass >
00595         inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) {
00596                 SetMementoFrom(x);
00597                 if (m_pStaticFunction!=0) {
00598                         // transform self references...
00599                         m_pthis=reinterpret_cast<GenericClass *>(pParent);
00600                 }
00601         }
00602         // For static functions, the 'static_function_invoker' class in the parent 
00603         // will be called. The parent then needs to call GetStaticFunction() to find out 
00604         // the actual function to invoke.
00605         template < class DerivedClass, class ParentInvokerSig >
00606         inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
00607                                 StaticFuncPtr function_to_bind ) {
00608                 if (function_to_bind==0) { // cope with assignment to 0
00609                         m_pFunction=0;
00610                 } else { 
00611                         bindmemfunc(pParent, static_function_invoker);
00612         }
00613                 m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
00614         }
00615         inline UnvoidStaticFuncPtr GetStaticFunction() const { 
00616                 return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction); 
00617         }
00618 #else
00619 
00620 //                              ClosurePtr<> - Evil version
00621 //
00622 // For compilers where data pointers are at least as big as code pointers, it is 
00623 // possible to store the function pointer in the this pointer, using another 
00624 // horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
00625 // speeds up comparison and assignment. If C++ provided direct language support
00626 // for delegates, they would produce asm code that was almost identical to this.
00627 // Note that the Sun C++ and MSVC documentation explicitly state that they 
00628 // support static_cast between void * and function pointers.
00629 
00630         template <class DerivedClass>
00631         inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) {
00632                 SetMementoFrom(right);
00633         }
00634         // For static functions, the 'static_function_invoker' class in the parent 
00635         // will be called. The parent then needs to call GetStaticFunction() to find out 
00636         // the actual function to invoke.
00637         // ******** EVIL, EVIL CODE! *******
00638         template <class DerivedClass, class ParentInvokerSig>
00639         inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 
00640                                 StaticFuncPtr function_to_bind) {
00641                 if (function_to_bind==0) { // cope with assignment to 0
00642                         m_pFunction=0;
00643                 } else { 
00644                    // We'll be ignoring the 'this' pointer, but we need to make sure we pass
00645                    // a valid value to bindmemfunc().
00646                         bindmemfunc(pParent, static_function_invoker);
00647         }
00648 
00649                 // WARNING! Evil hack. We store the function in the 'this' pointer!
00650                 // Ensure that there's a compilation failure if function pointers 
00651                 // and data pointers have different sizes.
00652                 // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
00653                 typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
00654                 m_pthis = horrible_cast<GenericClass *>(function_to_bind);
00655                 // MSVC, SunC++ and DMC accept the following (non-standard) code:
00656                 // m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
00657                 // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
00658                 // m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
00659         }
00660         // ******** EVIL, EVIL CODE! *******
00661         // This function will be called with an invalid 'this' pointer!!
00662         // We're just returning the 'this' pointer, converted into
00663         // a function pointer!
00664         inline UnvoidStaticFuncPtr GetStaticFunction() const {
00665                 // Ensure that there's a compilation failure if function pointers 
00666                 // and data pointers have different sizes.
00667                 // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
00668                 typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
00669                 return horrible_cast<UnvoidStaticFuncPtr>(this);
00670         }
00671 #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
00672 
00673         // Does the closure contain this static function?
00674         inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){
00675                 if (funcptr==0) return Empty(); 
00676         // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
00677         // value that is not equal to any valid function pointer.
00678                 else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
00679         }
00680 };
00681 
00682 
00683 } // namespace Internal
00684 
00686 //                                              Fast Delegates, part 3:
00687 //
00688 //                              Wrapper classes to ensure type safety
00689 //
00691 
00692 
00693 // Once we have the member function conversion templates, it's easy to make the
00694 // wrapper classes. So that they will work with as many compilers as possible, 
00695 // the classes are of the form
00696 //   FastDelegate3<int, char *, double>
00697 // They can cope with any combination of parameters. The max number of parameters
00698 // allowed is 8, but it is trivial to increase this limit.
00699 // Note that we need to treat const member functions seperately.
00700 // All this class does is to enforce type safety, and invoke the delegate with
00701 // the correct list of parameters.
00702 
00703 // Because of the weird rule about the class of derived member function pointers,
00704 // you sometimes need to apply a downcast to the 'this' pointer.
00705 // This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below. 
00706 // If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
00707 // without this trick you'd need to write:
00708 //              MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
00709 // but with the trick you can write
00710 //              MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
00711 
00712 // RetType is the type the compiler uses in compiling the template. For VC6,
00713 // it cannot be void. DesiredRetType is the real type which is returned from
00714 // all of the functions. It can be void.
00715 
00716 // Implicit conversion to "bool" is achieved using the safe_bool idiom,
00717 // using member data pointers (MDP). This allows "if (dg)..." syntax
00718 // Because some compilers (eg codeplay) don't have a unique value for a zero
00719 // MDP, an extra padding member is added to the SafeBool struct.
00720 // Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
00721 // in that case the static function constructor is not made explicit; this
00722 // allows "if (dg==0) ..." to compile.
00723 
00724 
00725 /*
00726         Member function names modified:
00727                 bind -> Bind
00728                 empty -> IsEmpty
00729                 clear -> Clear
00730         
00731         Functions GetMemento and SetMemento: public -> protected
00732         
00733         Lauri Kirikal
00734 */
00735 
00736 // N=0
00737 template<class RetType=Internal::DefaultVoid>
00738 class FastDelegate0 {
00739 private:
00740         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
00741         typedef DesiredRetType (*StaticFunctionPtr)();
00742         typedef RetType (*UnvoidStaticFunctionPtr)();
00743         typedef RetType (Internal::GenericClass::*GenericMemFn)();
00744         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00745         ClosureType m_Closure;
00746 public:
00747         // Typedefs to aid generic programming
00748         typedef FastDelegate0 type;
00749 
00750         // Construction and comparison functions
00751         FastDelegate0() { Clear(); }
00752         FastDelegate0(const FastDelegate0 &x) {
00753                 m_Closure.CopyFrom(this, x.m_Closure); }
00754         void operator = (const FastDelegate0 &x)  {
00755                 m_Closure.CopyFrom(this, x.m_Closure); }
00756         bool operator ==(const FastDelegate0 &x) const {
00757                 return m_Closure.IsEqual(x.m_Closure);  }
00758         bool operator !=(const FastDelegate0 &x) const {
00759                 return !m_Closure.IsEqual(x.m_Closure); }
00760         bool operator <(const FastDelegate0 &x) const {
00761                 return m_Closure.IsLess(x.m_Closure);   }
00762         bool operator >(const FastDelegate0 &x) const {
00763                 return x.m_Closure.IsLess(m_Closure);   }
00764         // Binding to non-const member functions
00765         template < class X, class Y >
00766         FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) {
00767                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
00768         template < class X, class Y >
00769         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) {
00770                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
00771         // Binding to const member functions.
00772         template < class X, class Y >
00773         FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
00774                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
00775         template < class X, class Y >
00776         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
00777                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
00778         // Static functions. We convert them into a member function call.
00779         // This constructor also provides implicit conversion
00780         FastDelegate0(DesiredRetType (*function_to_bind)() ) {
00781                 Bind(function_to_bind); }
00782         // for efficiency, prevent creation of a temporary
00783         void operator = (DesiredRetType (*function_to_bind)() ) {
00784                 Bind(function_to_bind); }
00785         inline void Bind(DesiredRetType (*function_to_bind)()) {
00786                 m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, 
00787                         function_to_bind); }
00788         // Invoke the delegate
00789         RetType Invoke() const {
00790         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); }
00791         inline RetType operator() () const {
00792         return Invoke(); }
00793         // Implicit conversion to "bool" using the safe_bool idiom
00794 private:
00795         typedef struct SafeBoolStruct {
00796                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
00797                 StaticFunctionPtr m_nonzero;
00798         } UselessTypedef;
00799     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
00800 public:
00801         operator unspecified_bool_type() const {
00802         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
00803     }
00804         // necessary to allow ==0 to work despite the safe_bool idiom
00805         inline bool operator==(StaticFunctionPtr funcptr) {
00806                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
00807         inline bool operator!=(StaticFunctionPtr funcptr) { 
00808                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
00809         inline bool operator ! () const {       // Is it bound to anything?
00810                         return !m_Closure; }
00811         inline bool IsEmpty() const     {
00812                         return !m_Closure; }
00813         void Clear() { m_Closure.Clear(); }
00814 protected:
00815         // Conversion to and from the DelegateMemento storage class
00816         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
00817         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
00818 private:        // Invoker for static functions
00819         RetType InvokeStaticFunction() const {
00820         return (*(m_Closure.GetStaticFunction()))(); }
00821 };
00822 
00823 // N=1
00824 template<class Param1, class RetType=Internal::DefaultVoid>
00825 class FastDelegate1 {
00826 private:
00827         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
00828         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
00829         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
00830         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1);
00831         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00832         ClosureType m_Closure;
00833 public:
00834         // Typedefs to aid generic programming
00835         typedef FastDelegate1 type;
00836 
00837         // Construction and comparison functions
00838         FastDelegate1() { Clear(); }
00839         FastDelegate1(const FastDelegate1 &x) {
00840                 m_Closure.CopyFrom(this, x.m_Closure); }
00841         void operator = (const FastDelegate1 &x)  {
00842                 m_Closure.CopyFrom(this, x.m_Closure); }
00843         bool operator ==(const FastDelegate1 &x) const {
00844                 return m_Closure.IsEqual(x.m_Closure);  }
00845         bool operator !=(const FastDelegate1 &x) const {
00846                 return !m_Closure.IsEqual(x.m_Closure); }
00847         bool operator <(const FastDelegate1 &x) const {
00848                 return m_Closure.IsLess(x.m_Closure);   }
00849         bool operator >(const FastDelegate1 &x) const {
00850                 return x.m_Closure.IsLess(m_Closure);   }
00851         // Binding to non-const member functions
00852         template < class X, class Y >
00853         FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) {
00854                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
00855         template < class X, class Y >
00856         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) {
00857                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
00858         // Binding to const member functions.
00859         template < class X, class Y >
00860         FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
00861                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
00862         template < class X, class Y >
00863         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
00864                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
00865         // Static functions. We convert them into a member function call.
00866         // This constructor also provides implicit conversion
00867         FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) {
00868                 Bind(function_to_bind); }
00869         // for efficiency, prevent creation of a temporary
00870         void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) {
00871                 Bind(function_to_bind); }
00872         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1)) {
00873                 m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, 
00874                         function_to_bind); }
00875         // Invoke the delegate
00876         RetType Invoke(Param1 p1) const {
00877         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); }
00878         inline RetType operator() (Param1 p1) const {
00879         return Invoke(p1); }
00880         // Implicit conversion to "bool" using the safe_bool idiom
00881 private:
00882         typedef struct SafeBoolStruct {
00883                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
00884                 StaticFunctionPtr m_nonzero;
00885         } UselessTypedef;
00886     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
00887 public:
00888         operator unspecified_bool_type() const {
00889         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
00890     }
00891         // necessary to allow ==0 to work despite the safe_bool idiom
00892         inline bool operator==(StaticFunctionPtr funcptr) {
00893                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
00894         inline bool operator!=(StaticFunctionPtr funcptr) { 
00895                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
00896         inline bool operator ! () const {       // Is it bound to anything?
00897                         return !m_Closure; }
00898         inline bool IsEmpty() const     {
00899                         return !m_Closure; }
00900         void Clear() { m_Closure.Clear(); }
00901 protected:
00902         // Conversion to and from the DelegateMemento storage class
00903         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
00904         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
00905 private:        // Invoker for static functions
00906         RetType InvokeStaticFunction(Param1 p1) const {
00907         return (*(m_Closure.GetStaticFunction()))(p1); }
00908 };
00909 
00910 //N=2
00911 template<class Param1, class Param2, class RetType=Internal::DefaultVoid>
00912 class FastDelegate2 {
00913 private:
00914         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
00915         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
00916         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
00917         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
00918         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
00919         ClosureType m_Closure;
00920 public:
00921         // Typedefs to aid generic programming
00922         typedef FastDelegate2 type;
00923 
00924         // Construction and comparison functions
00925         FastDelegate2() { Clear(); }
00926         FastDelegate2(const FastDelegate2 &x) {
00927                 m_Closure.CopyFrom(this, x.m_Closure); }
00928         void operator = (const FastDelegate2 &x)  {
00929                 m_Closure.CopyFrom(this, x.m_Closure); }
00930         bool operator ==(const FastDelegate2 &x) const {
00931                 return m_Closure.IsEqual(x.m_Closure);  }
00932         bool operator !=(const FastDelegate2 &x) const {
00933                 return !m_Closure.IsEqual(x.m_Closure); }
00934         bool operator <(const FastDelegate2 &x) const {
00935                 return m_Closure.IsLess(x.m_Closure);   }
00936         bool operator >(const FastDelegate2 &x) const {
00937                 return x.m_Closure.IsLess(m_Closure);   }
00938         // Binding to non-const member functions
00939         template < class X, class Y >
00940         FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) {
00941                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
00942         template < class X, class Y >
00943         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) {
00944                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
00945         // Binding to const member functions.
00946         template < class X, class Y >
00947         FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
00948                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
00949         template < class X, class Y >
00950         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
00951                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
00952         // Static functions. We convert them into a member function call.
00953         // This constructor also provides implicit conversion
00954         FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
00955                 Bind(function_to_bind); }
00956         // for efficiency, prevent creation of a temporary
00957         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
00958                 Bind(function_to_bind); }
00959         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) {
00960                 m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, 
00961                         function_to_bind); }
00962         // Invoke the delegate
00963         RetType operator() (Param1 p1, Param2 p2) const {
00964         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); }
00965         // Implicit conversion to "bool" using the safe_bool idiom
00966 private:
00967         typedef struct SafeBoolStruct {
00968                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
00969                 StaticFunctionPtr m_nonzero;
00970         } UselessTypedef;
00971     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
00972 public:
00973         operator unspecified_bool_type() const {
00974         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
00975     }
00976         // necessary to allow ==0 to work despite the safe_bool idiom
00977         inline bool operator==(StaticFunctionPtr funcptr) {
00978                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
00979         inline bool operator!=(StaticFunctionPtr funcptr) { 
00980                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
00981         inline bool operator ! () const {       // Is it bound to anything?
00982                         return !m_Closure; }
00983         inline bool IsEmpty() const     {
00984                         return !m_Closure; }
00985         void Clear() { m_Closure.Clear();}
00986 protected:
00987         // Conversion to and from the DelegateMemento storage class
00988         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
00989         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
00990 
00991 private:        // Invoker for static functions
00992         RetType InvokeStaticFunction(Param1 p1, Param2 p2) const {
00993         return (*(m_Closure.GetStaticFunction()))(p1, p2); }
00994 };
00995 
00996 //N=3
00997 template<class Param1, class Param2, class Param3, class RetType=Internal::DefaultVoid>
00998 class FastDelegate3 {
00999 private:
01000         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
01001         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
01002         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
01003         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
01004         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01005         ClosureType m_Closure;
01006 public:
01007         // Typedefs to aid generic programming
01008         typedef FastDelegate3 type;
01009 
01010         // Construction and comparison functions
01011         FastDelegate3() { Clear(); }
01012         FastDelegate3(const FastDelegate3 &x) {
01013                 m_Closure.CopyFrom(this, x.m_Closure); }
01014         void operator = (const FastDelegate3 &x)  {
01015                 m_Closure.CopyFrom(this, x.m_Closure); }
01016         bool operator ==(const FastDelegate3 &x) const {
01017                 return m_Closure.IsEqual(x.m_Closure);  }
01018         bool operator !=(const FastDelegate3 &x) const {
01019                 return !m_Closure.IsEqual(x.m_Closure); }
01020         bool operator <(const FastDelegate3 &x) const {
01021                 return m_Closure.IsLess(x.m_Closure);   }
01022         bool operator >(const FastDelegate3 &x) const {
01023                 return x.m_Closure.IsLess(m_Closure);   }
01024         // Binding to non-const member functions
01025         template < class X, class Y >
01026         FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01027                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
01028         template < class X, class Y >
01029         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
01030                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
01031         // Binding to const member functions.
01032         template < class X, class Y >
01033         FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
01034                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
01035         template < class X, class Y >
01036         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
01037                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
01038         // Static functions. We convert them into a member function call.
01039         // This constructor also provides implicit conversion
01040         FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01041                 Bind(function_to_bind); }
01042         // for efficiency, prevent creation of a temporary
01043         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
01044                 Bind(function_to_bind); }
01045         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
01046                 m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, 
01047                         function_to_bind); }
01048         // Invoke the delegate
01049         RetType operator() (Param1 p1, Param2 p2, Param3 p3) const {
01050         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); }
01051         // Implicit conversion to "bool" using the safe_bool idiom
01052 private:
01053         typedef struct SafeBoolStruct {
01054                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01055                 StaticFunctionPtr m_nonzero;
01056         } UselessTypedef;
01057     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01058 public:
01059         operator unspecified_bool_type() const {
01060         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
01061     }
01062         // necessary to allow ==0 to work despite the safe_bool idiom
01063         inline bool operator==(StaticFunctionPtr funcptr) {
01064                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01065         inline bool operator!=(StaticFunctionPtr funcptr) { 
01066                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01067         inline bool operator ! () const {       // Is it bound to anything?
01068                         return !m_Closure; }
01069         inline bool IsEmpty() const     {
01070                         return !m_Closure; }
01071         void Clear() { m_Closure.Clear();}
01072 protected:
01073         // Conversion to and from the DelegateMemento storage class
01074         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
01075         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01076 
01077 private:        // Invoker for static functions
01078         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const {
01079         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); }
01080 };
01081 
01082 //N=4
01083 template<class Param1, class Param2, class Param3, class Param4, class RetType=Internal::DefaultVoid>
01084 class FastDelegate4 {
01085 private:
01086         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
01087         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01088         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01089         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
01090         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01091         ClosureType m_Closure;
01092 public:
01093         // Typedefs to aid generic programming
01094         typedef FastDelegate4 type;
01095 
01096         // Construction and comparison functions
01097         FastDelegate4() { Clear(); }
01098         FastDelegate4(const FastDelegate4 &x) {
01099                 m_Closure.CopyFrom(this, x.m_Closure); }
01100         void operator = (const FastDelegate4 &x)  {
01101                 m_Closure.CopyFrom(this, x.m_Closure); }
01102         bool operator ==(const FastDelegate4 &x) const {
01103                 return m_Closure.IsEqual(x.m_Closure);  }
01104         bool operator !=(const FastDelegate4 &x) const {
01105                 return !m_Closure.IsEqual(x.m_Closure); }
01106         bool operator <(const FastDelegate4 &x) const {
01107                 return m_Closure.IsLess(x.m_Closure);   }
01108         bool operator >(const FastDelegate4 &x) const {
01109                 return x.m_Closure.IsLess(m_Closure);   }
01110         // Binding to non-const member functions
01111         template < class X, class Y >
01112         FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01113                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
01114         template < class X, class Y >
01115         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
01116                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
01117         // Binding to const member functions.
01118         template < class X, class Y >
01119         FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
01120                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
01121         template < class X, class Y >
01122         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
01123                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
01124         // Static functions. We convert them into a member function call.
01125         // This constructor also provides implicit conversion
01126         FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01127                 Bind(function_to_bind); }
01128         // for efficiency, prevent creation of a temporary
01129         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
01130                 Bind(function_to_bind); }
01131         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
01132                 m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, 
01133                         function_to_bind); }
01134         // Invoke the delegate
01135         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
01136         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); }
01137         // Implicit conversion to "bool" using the safe_bool idiom
01138 private:
01139         typedef struct SafeBoolStruct {
01140                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01141                 StaticFunctionPtr m_nonzero;
01142         } UselessTypedef;
01143     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01144 public:
01145         operator unspecified_bool_type() const {
01146         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
01147     }
01148         // necessary to allow ==0 to work despite the safe_bool idiom
01149         inline bool operator==(StaticFunctionPtr funcptr) {
01150                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01151         inline bool operator!=(StaticFunctionPtr funcptr) { 
01152                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01153         inline bool operator ! () const {       // Is it bound to anything?
01154                         return !m_Closure; }
01155         inline bool IsEmpty() const     {
01156                         return !m_Closure; }
01157         void Clear() { m_Closure.Clear();}
01158 protected:      
01159         // Conversion to and from the DelegateMemento storage class
01160         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
01161         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01162 
01163 private:        // Invoker for static functions
01164         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
01165         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); }
01166 };
01167 
01168 //N=5
01169 template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=Internal::DefaultVoid>
01170 class FastDelegate5 {
01171 private:
01172         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
01173         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01174         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01175         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
01176         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01177         ClosureType m_Closure;
01178 public:
01179         // Typedefs to aid generic programming
01180         typedef FastDelegate5 type;
01181 
01182         // Construction and comparison functions
01183         FastDelegate5() { Clear(); }
01184         FastDelegate5(const FastDelegate5 &x) {
01185                 m_Closure.CopyFrom(this, x.m_Closure); }
01186         void operator = (const FastDelegate5 &x)  {
01187                 m_Closure.CopyFrom(this, x.m_Closure); }
01188         bool operator ==(const FastDelegate5 &x) const {
01189                 return m_Closure.IsEqual(x.m_Closure);  }
01190         bool operator !=(const FastDelegate5 &x) const {
01191                 return !m_Closure.IsEqual(x.m_Closure); }
01192         bool operator <(const FastDelegate5 &x) const {
01193                 return m_Closure.IsLess(x.m_Closure);   }
01194         bool operator >(const FastDelegate5 &x) const {
01195                 return x.m_Closure.IsLess(m_Closure);   }
01196         // Binding to non-const member functions
01197         template < class X, class Y >
01198         FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01199                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
01200         template < class X, class Y >
01201         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
01202                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
01203         // Binding to const member functions.
01204         template < class X, class Y >
01205         FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
01206                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
01207         template < class X, class Y >
01208         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
01209                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
01210         // Static functions. We convert them into a member function call.
01211         // This constructor also provides implicit conversion
01212         FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01213                 Bind(function_to_bind); }
01214         // for efficiency, prevent creation of a temporary
01215         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
01216                 Bind(function_to_bind); }
01217         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
01218                 m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, 
01219                         function_to_bind); }
01220         // Invoke the delegate
01221         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
01222         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); }
01223         // Implicit conversion to "bool" using the safe_bool idiom
01224 private:
01225         typedef struct SafeBoolStruct {
01226                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01227                 StaticFunctionPtr m_nonzero;
01228         } UselessTypedef;
01229     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01230 public:
01231         operator unspecified_bool_type() const {
01232         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
01233     }
01234         // necessary to allow ==0 to work despite the safe_bool idiom
01235         inline bool operator==(StaticFunctionPtr funcptr) {
01236                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01237         inline bool operator!=(StaticFunctionPtr funcptr) { 
01238                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01239         inline bool operator ! () const {       // Is it bound to anything?
01240                         return !m_Closure; }
01241         inline bool IsEmpty() const     {
01242                         return !m_Closure; }
01243         void Clear() { m_Closure.Clear();}
01244 protected:
01245         // Conversion to and from the DelegateMemento storage class
01246         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
01247         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01248 
01249 private:        // Invoker for static functions
01250         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
01251         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); }
01252 };
01253 
01254 //N=6
01255 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=Internal::DefaultVoid>
01256 class FastDelegate6 {
01257 private:
01258         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
01259         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01260         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01261         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
01262         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01263         ClosureType m_Closure;
01264 public:
01265         // Typedefs to aid generic programming
01266         typedef FastDelegate6 type;
01267 
01268         // Construction and comparison functions
01269         FastDelegate6() { Clear(); }
01270         FastDelegate6(const FastDelegate6 &x) {
01271                 m_Closure.CopyFrom(this, x.m_Closure); }
01272         void operator = (const FastDelegate6 &x)  {
01273                 m_Closure.CopyFrom(this, x.m_Closure); }
01274         bool operator ==(const FastDelegate6 &x) const {
01275                 return m_Closure.IsEqual(x.m_Closure);  }
01276         bool operator !=(const FastDelegate6 &x) const {
01277                 return !m_Closure.IsEqual(x.m_Closure); }
01278         bool operator <(const FastDelegate6 &x) const {
01279                 return m_Closure.IsLess(x.m_Closure);   }
01280         bool operator >(const FastDelegate6 &x) const {
01281                 return x.m_Closure.IsLess(m_Closure);   }
01282         // Binding to non-const member functions
01283         template < class X, class Y >
01284         FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01285                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
01286         template < class X, class Y >
01287         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
01288                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
01289         // Binding to const member functions.
01290         template < class X, class Y >
01291         FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
01292                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
01293         template < class X, class Y >
01294         inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
01295                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
01296         // Static functions. We convert them into a member function call.
01297         // This constructor also provides implicit conversion
01298         FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01299                 Bind(function_to_bind); }
01300         // for efficiency, prevent creation of a temporary
01301         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
01302                 Bind(function_to_bind); }
01303         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
01304                 m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, 
01305                         function_to_bind); }
01306         // Invoke the delegate
01307         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
01308         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); }
01309         // Implicit conversion to "bool" using the safe_bool idiom
01310 private:
01311         typedef struct SafeBoolStruct {
01312                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01313                 StaticFunctionPtr m_nonzero;
01314         } UselessTypedef;
01315     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01316 public:
01317         operator unspecified_bool_type() const {
01318         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
01319     }
01320         // necessary to allow ==0 to work despite the safe_bool idiom
01321         inline bool operator==(StaticFunctionPtr funcptr) {
01322                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01323         inline bool operator!=(StaticFunctionPtr funcptr) { 
01324                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01325         inline bool operator ! () const {       // Is it bound to anything?
01326                         return !m_Closure; }
01327         inline bool IsEmpty() const     {
01328                         return !m_Closure; }
01329         void Clear() { m_Closure.Clear();}
01330 protected:
01331         // Conversion to and from the DelegateMemento storage class
01332         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
01333         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01334 
01335 private:        // Invoker for static functions
01336         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
01337         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); }
01338 };
01339 
01340 //N=7
01341 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=Internal::DefaultVoid>
01342 class FastDelegate7 {
01343 private:
01344         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
01345         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01346         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01347         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
01348         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01349         ClosureType m_Closure;
01350 public:
01351         // Typedefs to aid generic programming
01352         typedef FastDelegate7 type;
01353 
01354         // Construction and comparison functions
01355         FastDelegate7() { Clear(); }
01356         FastDelegate7(const FastDelegate7 &x) {
01357                 m_Closure.CopyFrom(this, x.m_Closure); }
01358         void operator = (const FastDelegate7 &x)  {
01359                 m_Closure.CopyFrom(this, x.m_Closure); }
01360         bool operator ==(const FastDelegate7 &x) const {
01361                 return m_Closure.IsEqual(x.m_Closure);  }
01362         bool operator !=(const FastDelegate7 &x) const {
01363                 return !m_Closure.IsEqual(x.m_Closure); }
01364         bool operator <(const FastDelegate7 &x) const {
01365                 return m_Closure.IsLess(x.m_Closure);   }
01366         bool operator >(const FastDelegate7 &x) const {
01367                 return x.m_Closure.IsLess(m_Closure);   }
01368         // Binding to non-const member functions
01369         template < class X, class Y >
01370         FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01371                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
01372         template < class X, class Y >
01373         inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
01374                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
01375         // Binding to const member functions.
01376         template < class X, class Y >
01377         FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
01378                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
01379         template < class X, class Y >
01380         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) {
01381                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
01382         // Static functions. We convert them into a member function call.
01383         // This constructor also provides implicit conversion
01384         FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01385                 Bind(function_to_bind); }
01386         // for efficiency, prevent creation of a temporary
01387         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
01388                 Bind(function_to_bind); }
01389         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
01390                 m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, 
01391                         function_to_bind); }
01392         // Invoke the delegate
01393         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
01394         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); }
01395         // Implicit conversion to "bool" using the safe_bool idiom
01396 private:
01397         typedef struct SafeBoolStruct {
01398                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01399                 StaticFunctionPtr m_nonzero;
01400         } UselessTypedef;
01401     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01402 public:
01403         operator unspecified_bool_type() const {
01404         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
01405     }
01406         // necessary to allow ==0 to work despite the safe_bool idiom
01407         inline bool operator==(StaticFunctionPtr funcptr) {
01408                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01409         inline bool operator!=(StaticFunctionPtr funcptr) { 
01410                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01411         inline bool operator ! () const {       // Is it bound to anything?
01412                         return !m_Closure; }
01413         inline bool IsEmpty() const     {
01414                         return !m_Closure; }
01415         void Clear() { m_Closure.Clear();}
01416 protected:
01417         // Conversion to and from the DelegateMemento storage class
01418         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
01419         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01420 
01421 private:        // Invoker for static functions
01422         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
01423         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); }
01424 };
01425 
01426 //N=8
01427 template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=Internal::DefaultVoid>
01428 class FastDelegate8 {
01429 private:
01430         typedef typename Internal::DefaultVoidToVoid<RetType>::type DesiredRetType;
01431         typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01432         typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01433         typedef RetType (Internal::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
01434         typedef Internal::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
01435         ClosureType m_Closure;
01436 public:
01437         // Typedefs to aid generic programming
01438         typedef FastDelegate8 type;
01439 
01440         // Construction and comparison functions
01441         FastDelegate8() { Clear(); }
01442         FastDelegate8(const FastDelegate8 &x) {
01443                 m_Closure.CopyFrom(this, x.m_Closure); }
01444         void operator = (const FastDelegate8 &x)  {
01445                 m_Closure.CopyFrom(this, x.m_Closure); }
01446         bool operator ==(const FastDelegate8 &x) const {
01447                 return m_Closure.IsEqual(x.m_Closure);  }
01448         bool operator !=(const FastDelegate8 &x) const {
01449                 return !m_Closure.IsEqual(x.m_Closure); }
01450         bool operator <(const FastDelegate8 &x) const {
01451                 return m_Closure.IsLess(x.m_Closure);   }
01452         bool operator >(const FastDelegate8 &x) const {
01453                 return x.m_Closure.IsLess(m_Closure);   }
01454         // Binding to non-const member functions
01455         template < class X, class Y >
01456         FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01457                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind); }
01458         template < class X, class Y >
01459         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)) {
01460                 m_Closure.bindmemfunc(Internal::implicit_cast<X*>(pthis), function_to_bind);    }
01461         // Binding to const member functions.
01462         template < class X, class Y >
01463         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) {
01464                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X*>(pthis), function_to_bind); }
01465         template < class X, class Y >
01466         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) {
01467                 m_Closure.bindconstmemfunc(Internal::implicit_cast<const X *>(pthis), function_to_bind);        }
01468         // Static functions. We convert them into a member function call.
01469         // This constructor also provides implicit conversion
01470         FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01471                 Bind(function_to_bind); }
01472         // for efficiency, prevent creation of a temporary
01473         void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
01474                 Bind(function_to_bind); }
01475         inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
01476                 m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, 
01477                         function_to_bind); }
01478         // Invoke the delegate
01479         RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
01480         return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); }
01481         // Implicit conversion to "bool" using the safe_bool idiom
01482 private:
01483         typedef struct SafeBoolStruct {
01484                 int a_data_pointer_to_this_is_0_on_buggy_compilers;
01485                 StaticFunctionPtr m_nonzero;
01486         } UselessTypedef;
01487     typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
01488 public:
01489         operator unspecified_bool_type() const {
01490         return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
01491     }
01492         // necessary to allow ==0 to work despite the safe_bool idiom
01493         inline bool operator==(StaticFunctionPtr funcptr) {
01494                 return m_Closure.IsEqualToStaticFuncPtr(funcptr);       }
01495         inline bool operator!=(StaticFunctionPtr funcptr) { 
01496                 return !m_Closure.IsEqualToStaticFuncPtr(funcptr);    }
01497         inline bool operator ! () const {       // Is it bound to anything?
01498                         return !m_Closure; }
01499         inline bool IsEmpty() const     {
01500                         return !m_Closure; }
01501         void Clear() { m_Closure.Clear();}
01502 protected:
01503         // Conversion to and from the DelegateMemento storage class
01504         const Internal::DelegateMemento & GetMemento() { return m_Closure; }
01505         void SetMemento(const Internal::DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
01506 
01507 private:        // Invoker for static functions
01508         RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
01509         return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); }
01510 };
01511 
01512 /*
01513         ... part 4, part 5 ERASED ...
01514 
01515         And now on only AVR-specific code with GPL license
01516 
01517         Lauri Kirikal
01518  */
01519 
01520 /**********************************************************************************************************************\
01521 
01522         C++ library for Atmel AVR microcontrollers
01523         Copyright (C) 2007 Lauri Kirikal, Mikk Leini, MT� TT� Robotiklubi
01524 
01525         This program is free software; you can redistribute it and/or
01526         modify it under the terms of the GNU General Public License
01527         as published by the Free Software Foundation; either version 2
01528         of the License, or (at your option) any later version.
01529 
01530         This program is distributed in the hope that it will be useful,
01531         but WITHOUT ANY WARRANTY; without even the implied warranty of
01532         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01533         GNU General Public License for more details.
01534 
01535         You should have received a copy of the GNU General Public License
01536         along with this program; if not, write to the Free Software
01537         Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
01538 
01539         See http://creativecommons.org/licenses/GPL/2.0/
01540 
01541         MT� TT� Robotiklubi  http://www.robotiklubi.ee robotiklubi@gmail.com
01542         Lauri Kirikal        laurikirikal@gmail.com
01543         Mikk Leini           mikk.leini@gmail.com
01544 
01545 \**********************************************************************************************************************/
01546 
01547 #ifndef EXCLUDE_FAST_DELEGATE
01548         typedef FastDelegate0<void> FastDelegate;
01549 #endif
01550 
01551 #if !defined(EXCLUDE_DATA_DELEGATE) || !defined(EXCLUDE_MULTI_DELEGATE)
01552 
01553         namespace Internal
01554         {
01555                 template <class Delegate, class FastDelegate> bool AddFastDelegate(Delegate &delegate, FastDelegate &addable)
01556                 {
01557                         
01558                         if (!delegate.me)
01559                         {
01560                                 delegate.me = addable;
01561                         }
01562                         else
01563                         {
01564                                 if (delegate.next == NULL)
01565                                 {
01566                                         delegate.next = new Delegate(addable);
01567                                         if (delegate.next == NULL) return false;
01568                                 }
01569                                 else
01570                                 {
01571                                         return delegate.next->Add(addable);
01572                                 }
01573                         }
01574                         
01575                         return true;
01576                         
01577                 } // AddFastDelegate
01578                 
01579                 template <class Delegate, typename Function> bool AddFunction(Delegate &delegate, Function function)
01580                 {
01581                         if (!delegate.me)
01582                         {
01583                                 delegate.me.Bind(function);
01584                         }
01585                         else
01586                         {
01587                                 if (delegate.next == NULL)
01588                                 {
01589                                         delegate.next = new Delegate(function);
01590                                         if (delegate.next == NULL) return false;
01591                                 }
01592                                 else
01593                                 {
01594                                         return delegate.next->Add(function);
01595                                 }
01596                         }
01597                         
01598                         return true;
01599                         
01600                 } // AddFunction
01601                 
01602                 template <class Delegate, class Object, typename MemberFunction>
01603                                 bool AddMemberFunction(Delegate &delegate, Object *object, MemberFunction function)
01604                 {
01605                         if (!delegate.me)
01606                         {
01607                                 delegate.me.Bind(object, function);
01608                         }
01609                         else
01610                         {
01611                                 if (delegate.next == NULL)
01612                                 {
01613                                         delegate.next = new Delegate(object, function);
01614                                         if (delegate.next == NULL) return false;
01615                                 }
01616                                 else
01617                                 {
01618                                         return delegate.next->Add(object, function);
01619                                 }
01620                         }
01621                         
01622                         return true;
01623                         
01624                 } // AddMemberFunction
01625                 
01626                 template <class Delegate, class FastDelegate> bool RemoveAll(Delegate &delegate, FastDelegate &removable)
01627                 {
01628                         if (removable == delegate.me)
01629                         {
01630                                 if (delegate.next == NULL)
01631                                 {
01632                                         delegate.me.Clear();
01633                                 }
01634                                 else
01635                                 {
01636                                         Delegate *cutOut, *cutOutNext = delegate.next;
01637                                         
01638                                         while (cutOutNext->me == removable)
01639                                         {
01640                                                 cutOut = cutOutNext;
01641                                                 cutOutNext = cutOut->next;
01642                                                 
01643                                                 delete cutOut;
01644                                                 
01645                                                 if (cutOutNext == NULL)
01646                                                 {
01647                                                         delegate.next = NULL;
01648                                                         delegate.me.Clear();
01649                                                         return true;
01650                                                 }
01651                                         }
01652                                         
01653                                         delegate.me = cutOutNext->me;
01654                                         delegate.next = cutOutNext->next;
01655                                         
01656                                         delete cutOutNext;
01657                                         
01658                                         if (delegate.next != NULL)
01659                                                 delegate.next->RemoveAll(removable);
01660                                         
01661                                 }
01662                         }
01663                         else
01664                         {
01665                                 if (delegate.next == NULL)
01666                                         return false;
01667                                 else
01668                                         return delegate.next->RemoveAll(removable);
01669                         }
01670                         
01671                         return true;
01672                         
01673                 } // RemoveAll
01674                 
01675                 template <class Delegate, class FastDelegate> bool Remove(Delegate &delegate, FastDelegate &removable)
01676                 {
01677                         if (removable == delegate.me)
01678                         {
01679                                 if (delegate.next == NULL)
01680                                 {
01681                                         delegate.me.Clear();
01682                                 }
01683                                 else
01684                                 {
01685                                         Delegate *cutOut = delegate.next;
01686                                         
01687                                         delegate.me = cutOut->me;
01688                                         delegate.next = cutOut->next;
01689                                         
01690                                         delete cutOut;
01691                                 }
01692                         }
01693                         else
01694                         {
01695                                 if (delegate.next == NULL)
01696                                         return false;
01697                                 else
01698                                         return delegate.next->Remove(removable);
01699                         }
01700                         
01701                         return true;
01702                         
01703                 } // Remove
01704                 
01705                 template <class Delegate> void Clear(Delegate &delegate)
01706                 {
01707                         if (delegate.next != NULL)
01708                         {
01709                                 delegate.next->Clear();
01710                                 delete delegate.next;
01711                                 delegate.next = NULL;
01712                         }
01713                         delegate.me.Clear();
01714                         
01715                 } // Clear
01716                 
01717         } // namespace Internal
01718 
01719 #endif // if !defined(EXCLUDE_DATA_DELEGATE) || !defined(EXCLUDE_MULTI_DELEGATE)
01720 
01721 #ifndef EXCLUDE_DATA_DELEGATE
01722 
01723         template<class Derived> class DelegateController;
01724 
01725         template <class Controller> class DataDelegate
01726         {
01727         public:
01728                 
01729                 typedef void (*Function)(Controller &);
01730                 typedef FastDelegate1<Controller &> FastDelegate;
01731                 
01732         private:
01733                 
01734                 friend class DelegateController<Controller>;
01735                 template <class Delegate, class FastDelegate> friend bool Internal::AddFastDelegate(Delegate &delegate, FastDelegate &addable);
01736                 template <class Delegate, typename Function> friend bool Internal::AddFunction(Delegate &delegate, Function function);
01737                 template <class Delegate, class Object, typename MemberFunction> friend bool Internal::AddMemberFunction(Delegate &delegate, Object *object, MemberFunction function);
01738                 template <class Delegate, class FastDelegate> friend bool Internal::RemoveAll(Delegate &delegate, FastDelegate &removable);
01739                 template <class Delegate, class FastDelegate> friend bool Internal::Remove(Delegate &delegate, FastDelegate &removable);
01740                 template <class Delegate> friend void Internal::Clear(Delegate &delegate);
01741                 
01742                 DataDelegate<Controller> *      next;
01743                 FastDelegate                            me;
01744                 
01745                 DataDelegate() : next(NULL), me() {}
01746                 DataDelegate(Function function) : next(NULL), me(function) {}
01747                 DataDelegate(const FastDelegate &_me) : next(NULL), me(_me) {}
01748                 template <class X, class Y> DataDelegate(X *object, void (Y::* function)(Controller &) ) : next(NULL), me(object, function) {}
01749                 template <class X, class Y> DataDelegate(const X *object, void (Y::* function)(Controller &) const) : next(NULL), me(object, function) {}
01750                 
01751                 void Invoke(Controller &controller) const
01752                 {
01753                         if (!me.IsEmpty() )
01754                         {
01755                                 me(controller);
01756                                 if (next != NULL) next->Invoke(controller);
01757                         }
01758                         
01759                 } // OPERATOR ()
01760                 
01761                 inline void operator() (Controller &controller) const { Invoke(controller); }
01762                 
01763         public:
01764 
01765                 inline bool Add(FastDelegate &addable)
01766                 {
01767                         return Internal::AddFastDelegate<DataDelegate<Controller>, FastDelegate>(*this, addable);
01768                         
01769                 } // Add 1
01770                 
01771                 inline bool Add(Function function)
01772                 {
01773                         return Internal::AddFunction<DataDelegate<Controller>, Function>(*this, function);
01774                         
01775                 } // Add 2
01776                 
01777                 template <class X, class Y> inline bool Add(X *object, void (Y::* function)(Controller &) )
01778                 {
01779                         return Internal::AddMemberFunction<DataDelegate<Controller>, X, void (Y::*)(Controller &)>(*this, object, function);
01780                         
01781                 } // Add 3
01782                 
01783                 template <class X, class Y> inline bool Add(const X *object, void (Y::* function)(Controller &) const)
01784                 {
01785                         return Internal::AddMemberFunction<DataDelegate<Controller>, const X, void (Y::*)(Controller &) const>(*this, object, function);
01786                         
01787                 } // Add 4
01788                 
01789                 inline bool RemoveAll(FastDelegate &removable)
01790                 {
01791                         return Internal::RemoveAll<DataDelegate<Controller>, Function>(*this, removable);
01792                         
01793                 } // RemoveAll 1
01794                 
01795                 inline bool RemoveAll(Function function)
01796                 {
01797                         FastDelegate removable(function);
01798                         
01799                         return RemoveAll(removable);
01800                         
01801                 } // RemoveAll 2
01802                 
01803                 template <class X, class Y> inline bool RemoveAll(X *object, void (Y::* function)(Controller &) )
01804                 {
01805                         FastDelegate removable(object, function);
01806                         
01807                         return RemoveAll(removable);
01808                         
01809                 } // RemoveAll 3
01810                 
01811                 template <class X, class Y> inline bool RemoveAll(const X *object, void (Y::* function)(Controller &) const)
01812                 {
01813                         FastDelegate removable(object, function);
01814                         
01815                         return RemoveAll(removable);
01816                         
01817                 } // RemoveAll 4
01818                 
01819                 inline bool Remove(FastDelegate &removable)
01820                 {
01821                         return Internal::Remove<DataDelegate<Controller>, FastDelegate>(*this, removable);
01822                         
01823                 } // Remove 1
01824                 
01825                 inline bool Remove(Function function)
01826                 {
01827                         FastDelegate removable(function);
01828                         
01829                         return Remove(removable);
01830                         
01831                 } // Remove 2
01832                 
01833                 template <class X, class Y> inline bool Remove(X *object, void (Y::* function)(Controller &) )
01834                 {
01835                         FastDelegate removable(object, function);
01836                         
01837                         return Remove(removable);
01838                         
01839                 } // Remove 3
01840                 
01841                 template <class X, class Y> inline bool Remove(const X *object, void (Y::* function)(Controller &) const)
01842                 {
01843                         FastDelegate removable(object, function);
01844                         
01845                         return Remove(removable);
01846                         
01847                 } // Remove 4
01848                 
01849                 inline void Clear() { Internal::Clear<DataDelegate<Controller> >(*this); }
01850                 inline bool IsEmpty() { return !me; }
01851                 inline bool operator ! () { return IsEmpty(); }
01852                 inline bool operator += (Function function) { return Add(function); }
01853                 inline bool operator += (FastDelegate &addable) { return Add(addable); }
01854                 inline bool operator -= (Function function) { return Remove(function); }
01855                 inline bool operator -= (FastDelegate &removable) { return Remove(removable); }
01856                 
01857                 ~DataDelegate() { Clear(); }
01858                 
01859         }; // class DataDelegate
01860         
01861         
01862         template <class Derived> class DelegateController
01863         {
01864         protected:
01865                 
01866                 virtual bool Before() = 0;
01867                 virtual void After() {};
01868                 
01869         private:
01870                 
01871                 DataDelegate<Derived> dataDelegate;
01872                 
01873         public:
01874                 
01875                 DelegateController() : dataDelegate() {}
01876                 DataDelegate<Derived> &Delegate() { return dataDelegate; }
01877                 
01878                 void Invoke()
01879                 {
01880                         if (Before() )
01881                         {
01882                                 dataDelegate(*((Derived *)this));
01883                                 After();
01884                         }
01885                         
01886                 } // operator ()
01887                 
01888                 inline void operator() () { Invoke(); }
01889                 virtual ~DelegateController() {}
01890                 
01891         }; // class DelegateController
01892 
01893 #endif // ifndef EXCLUDE_DATA_DELEGATE
01894 
01895 #ifndef EXCLUDE_MULTI_DELEGATE
01896         
01897         class MultiDelegate
01898         {
01899         public:
01900                 
01901                 typedef void (*Function)(void);
01902                 typedef FastDelegate0<> FastDelegate;
01903                 
01904         private:
01905                 
01906                 MultiDelegate * next;
01907                 FastDelegate    me;
01908                 
01909                 template <class Delegate, class FastDelegate> friend bool Internal::AddFastDelegate(Delegate &delegate, FastDelegate &addable);
01910                 template <class Delegate, typename Function> friend bool Internal::AddFunction(Delegate &delegate, Function function);
01911                 template <class Delegate, class Object, typename MemberFunction> friend bool Internal::AddMemberFunction(Delegate &delegate, Object *object, MemberFunction function);
01912                 template <class Delegate, class FastDelegate> friend bool Internal::RemoveAll(Delegate &delegate, FastDelegate &removable);
01913                 template <class Delegate, class FastDelegate> friend bool Internal::Remove(Delegate &delegate, FastDelegate &removable);
01914                 template <class Delegate> friend void Internal::Clear(Delegate &delegate);
01915                 
01916         public:
01917                 
01918                 MultiDelegate() : next(NULL), me() {}
01919                 MultiDelegate(Function function) : next(NULL), me(function) {}
01920                 MultiDelegate(const FastDelegate &_me) : next(NULL), me(_me) {}
01921                 template <class X, class Y> MultiDelegate(X *object, void (Y::* function)() ) : next(NULL), me(object, function) {}
01922                 template <class X, class Y> MultiDelegate(const X *object, void (Y::* function)() const) : next(NULL), me(object, function) {}
01923                 
01924                 void Invoke() const
01925                 {
01926                         if (!me.IsEmpty() )
01927                         {
01928                                 me();
01929                                 if (next != NULL) next->Invoke();
01930                         }
01931                         
01932                 } // OPERATOR ()
01933 
01934                 inline bool Add(FastDelegate &addable)
01935                 {
01936                         return Internal::AddFastDelegate<MultiDelegate, FastDelegate>(*this, addable);
01937                         
01938                 } // Add 1
01939                 
01940                 inline bool Add(Function function)
01941                 {
01942                         return Internal::AddFunction<MultiDelegate, Function>(*this, function);
01943                         
01944                 } // Add 2
01945 
01946                 template <class X, class Y> inline bool Add(X *object, void (Y::* function)() )
01947                 {
01948                         return Internal::AddMemberFunction<MultiDelegate, X, void (Y::*)()>(*this, object, function);
01949                         
01950                 } // Add 3
01951                 
01952                 template <class X, class Y> inline bool Add(const X *object, void (Y::* function)() const)
01953                 {
01954                         return Internal::AddMemberFunction<MultiDelegate, const X, void (Y::*)() const>(*this, object, function);
01955                         
01956                 } // Add 4
01957                 
01958                 inline bool RemoveAll(FastDelegate &removable)
01959                 {
01960                         return Internal::RemoveAll<MultiDelegate, FastDelegate>(*this, removable);
01961                         
01962                 } // RemoveAll 1
01963                 
01964                 inline bool RemoveAll(Function function)
01965                 {
01966                         FastDelegate removable(function);
01967                         
01968                         return RemoveAll(removable);
01969                         
01970                 } // RemoveAll 2
01971                 
01972                 template <class X, class Y> inline bool RemoveAll(X *object, void (Y::* function)() )
01973                 {
01974                         FastDelegate removable(object, function);
01975                         
01976                         return RemoveAll(removable);
01977                         
01978                 } // RemoveAll 3
01979                 
01980                 template <class X, class Y> inline bool RemoveAll(const X *object, void (Y::* function)() const)
01981                 {
01982                         return RemoveAll<X, Y>(object, (void (Y::*)(void))function);
01983                         
01984                 } // RemoveAll 4
01985                 
01986                 inline bool Remove(FastDelegate &removable)
01987                 {
01988                         return Internal::Remove<MultiDelegate, FastDelegate>(*this, removable);
01989                         
01990                 } // Remove 1
01991                 
01992                 inline bool Remove(Function function)
01993                 {
01994                         FastDelegate removable(function);
01995                         
01996                         return Remove(removable);
01997                         
01998                 } // Remove 2
01999                 
02000                 template <class X, class Y> inline bool Remove(X *object, void (Y::* function)() )
02001                 {
02002                         FastDelegate removable(object, function);
02003                         
02004                         return Remove(removable);
02005                         
02006                 } // Remove 3
02007                 
02008                 template <class X, class Y> inline bool Remove(const X *object, void (Y::* function)() const)
02009                 {
02010                         return Remove(object, (void (Y::*)(void))function);
02011                         
02012                 } // Remove 4
02013                 
02014                 inline void Clear() { Internal::Clear<MultiDelegate>(*this);    }
02015                 inline bool IsEmpty() const { return !me; }
02016                 inline void operator() () const { Invoke(); }
02017                 inline bool operator ! () const { return IsEmpty(); }
02018                 inline bool operator += (Function function) { return Add(function); }
02019                 inline bool operator += (FastDelegate &addable) { return Add(addable); }
02020                 inline bool operator -= (Function function) { return Remove(function); }
02021                 inline bool operator -= (FastDelegate &removable) { return Remove(removable); }
02022                 ~MultiDelegate() { Clear(); }
02023                 
02024         }; // class MultiDelegate
02025 
02026 #endif // ifndef EXCLUDE_MULTI_DELEGATE
02027 
02028  // clean up after ourselves...
02029 #undef FASTDLGT_RETTYPE
02030 
02031 } // namespace CppDelegate
02032 
02033 #endif // ifdef __cplusplus
02034 #endif // if !(defined(EXCLUDE_FAST_DELEGATE) && defined(EXCLUDE_MULTI_DELEGATE) && defined(EXLUDE_DATA_DELEGATE))
02035 #endif // ifndef __AVR_CPP_DELEGATE_H__
02036 

Generated on Sat Sep 15 23:41:46 2007 for AVR C++ Lib (common) by  doxygen 1.5.2
SourceForge.net Logo MTÜ TTÜ Robotiklubi