FastDelegate.h 122 KB

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