FastDelegate.h 95 KB

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