Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2707 lines
102 KiB

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