FastDelegate.h 102 KB

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