Team Fortress 2 Source Code as on 22/4/2020
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.

2656 lines
100 KiB

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