FastDelegate.h 102 KB

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