fork download
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. template<typename TFuncSignature>
  5. class Callback;
  6.  
  7. template<typename R, typename ...Arg>
  8. class Callback<R ( Arg... ) > {
  9. public:
  10. typedef R ( *TFunc ) ( void*, Arg... );
  11.  
  12. Callback() : obj ( 0 ), func ( 0 ) {}
  13. Callback ( void* o, TFunc f ) : obj ( o ), func ( f ) {}
  14.  
  15. R operator() ( Arg... a1 ) const {
  16. return ( *func ) ( obj, a1... );
  17. }
  18.  
  19. typedef void* Callback::* SafeBoolType;
  20. operator SafeBoolType () const {
  21. return func != 0 ? &Callback::obj : 0;
  22. }
  23.  
  24. bool operator! () const {
  25. return func == 0;
  26. }
  27.  
  28. bool operator== ( const Callback<R ( Arg... ) >& right ) const {
  29. return obj == right.obj && func == right.func;
  30. }
  31.  
  32. bool operator!= ( const Callback<R ( Arg... ) >& right ) const {
  33. return obj != right.obj || func != right.func;
  34. }
  35.  
  36. private:
  37. void* obj;
  38. TFunc func;
  39. };
  40.  
  41. template<typename R, class T, typename ...Arg>
  42. struct DeduceMemCallbackTag {
  43. template<R ( T::*Func ) ( Arg... ) >
  44. static R Wrapper ( void* o, Arg... a ) {
  45. return ( static_cast<T*> ( o )->*Func ) ( a... );
  46. }
  47.  
  48. template<R ( T::*Func ) ( Arg... ) >
  49. inline static Callback<R ( Arg... ) > Bind ( T* o ) {
  50. return Callback<R ( Arg... ) > ( o, &DeduceMemCallbackTag::Wrapper<Func> );
  51. }
  52. };
  53.  
  54. template<typename R, typename ...Arg>
  55. struct DeduceStaticCallbackTag {
  56. template<R ( *Func ) ( Arg... ) >
  57. static R Wrapper ( void*, Arg... a ) {
  58. return ( *Func ) ( a... );
  59. }
  60.  
  61. template<R ( *Func ) ( Arg... ) >
  62. inline static Callback<R ( Arg... ) > Bind( ) {
  63. return Callback<R ( Arg... ) > ( 0, &DeduceStaticCallbackTag::Wrapper<Func> );
  64. }
  65. };
  66.  
  67. template<typename R, class T, typename ...Arg>
  68. DeduceMemCallbackTag<R, T, Arg...> DeduceMemCallback ( R ( T::* ) ( Arg... ) ) {
  69. return DeduceMemCallbackTag<R, T, Arg...>();
  70. }
  71.  
  72. template<typename R, typename ...Arg>
  73. DeduceStaticCallbackTag<R, Arg...> DeduceStaticCallback ( R ( * ) ( Arg... ) ) {
  74. return DeduceStaticCallbackTag<R, Arg...>();
  75. }
  76.  
  77. template <typename... T1> class Event {
  78. public:
  79. typedef void ( * TSignature ) ( T1... );
  80. typedef Callback<void ( T1... ) > TCallback;
  81.  
  82. protected:
  83. std::vector<TCallback> invocations;
  84. std::vector<Event<T1...>*> events;
  85.  
  86. public:
  87. const static int ExpectedFunctorCount = 2;
  88.  
  89. Event () : invocations(), events() {
  90. invocations.reserve ( ExpectedFunctorCount );
  91. events.reserve ( ExpectedFunctorCount );
  92. }
  93.  
  94. template <void ( * TFunc ) ( T1... ) > void Add ( ) {
  95. TCallback c = DeduceStaticCallback ( TFunc ).template Bind< TFunc >( );
  96. invocations.push_back ( c );
  97. }
  98.  
  99. template <typename T, void ( T::* TFunc ) ( T1... ) > void Add ( T& object ) {
  100. Add<T, TFunc> ( &object );
  101. }
  102.  
  103. template <typename T, void ( T::* TFunc ) ( T1... ) > void Add ( T* object ) {
  104. TCallback c = DeduceMemCallback ( TFunc ).template Bind< TFunc > ( object );
  105. invocations.push_back ( c );
  106. }
  107.  
  108. void Invoke ( T1... t1 ) {
  109. size_t i;
  110. for ( i = 0; i < invocations.size(); ++i ) {
  111. invocations[i] ( t1... );
  112. }
  113. for ( i = 0; i < events.size(); ++i ) {
  114. ( *events[i] ) ( t1... );
  115. }
  116. }
  117.  
  118. void operator() ( T1... t1 ) {
  119. Invoke ( t1... );
  120. }
  121.  
  122. size_t InvocationCount ( ) {
  123. return events.size( ) + invocations.size( );
  124. }
  125.  
  126. template <void ( * TFunc ) ( T1... ) > bool Remove ( ) {
  127. TCallback target = DeduceStaticCallback ( TFunc ).template Bind< TFunc >( );
  128. for ( size_t i = 0; i < invocations.size(); ++i ) {
  129. TCallback& inv = invocations[i];
  130. if ( target == inv ) {
  131. invocations.erase ( invocations.begin() + i );
  132. return true;
  133. }
  134. }
  135. return false;
  136. }
  137.  
  138. template <typename T, void ( T::* TFunc ) ( T1... ) > bool Remove ( T& object ) {
  139. return Remove<T, TFunc> ( &object );
  140. }
  141.  
  142. template <typename T, void ( T::* TFunc ) ( T1... ) > bool Remove ( T* object ) {
  143. TCallback target = DeduceMemCallback ( TFunc ).template Bind< TFunc > ( object );
  144. for ( size_t i = 0; i < invocations.size(); ++i ) {
  145. TCallback& inv = invocations[i];
  146. if ( target == inv ) {
  147. invocations.erase ( invocations.begin() + i );
  148. return true;
  149. }
  150. }
  151. return false;
  152. }
  153.  
  154. };
  155.  
  156. namespace IntStatic {
  157. void VoidTest ( ) {
  158. std::cout << "INTO THE VOID" << std::endl;
  159. }
  160. void IntTest ( int num ) {
  161. std::cout << "Got myself a " << num << " !" << std::endl;
  162. }
  163. void IntTest2 ( int num ) {
  164. std::cout << "Now _I_ Got myself a " << num << " !" << std::endl;
  165. }
  166. }
  167.  
  168. struct Int {
  169. void Test ( int num ) {
  170. std::cout << num << " on the inside of a class... ?" << std::endl;
  171. }
  172. void Test2 ( int num ) {
  173. std::cout << num << " on the inside of a struct, yo !" << std::endl;
  174. }
  175. static void Test3 ( int snum ) {
  176. std::cout << snum << " on the inside of a STATIC method?!" << std::endl;
  177. }
  178. };
  179.  
  180. struct Multi {
  181. void Test ( std::string woo, std::string yeah ) {
  182. std::cout << "Dat Multi Member Function: ";
  183. std::cout << woo << " | " << yeah << std::endl;
  184. }
  185.  
  186. void static Test2 ( std::string woo, std::string yeah ) {
  187. std::cout << "Dat Static Multi Function: ";
  188. std::cout << woo << " | " << yeah << std::endl;
  189. }
  190. };
  191.  
  192. int main ( int argc, char* argv[] ) {
  193.  
  194. Event<int> intev;
  195. Int i;
  196. Multi m;
  197.  
  198. intev.Add<Int, &Int::Test>(i);
  199. intev.Add<&IntStatic::IntTest>();
  200. intev.Add<&IntStatic::IntTest2>();
  201. intev(20);
  202. intev.Remove<&IntStatic::IntTest>();
  203. intev.Remove<&IntStatic::IntTest>();
  204. intev.Remove<Int, &Int::Test>(i);
  205. intev(20);
  206.  
  207. Event<std::string, std::string> doublestringev;
  208.  
  209. doublestringev.Add<Multi, &Multi::Test>( m );
  210. doublestringev( "Bark Bark", "Meow Meow" );
  211. doublestringev.Remove<Multi, &Multi::Test>( m );
  212.  
  213. doublestringev.Add<&Multi::Test2>( );
  214. doublestringev( "Bahh Bahh", "Moo Moo" );
  215.  
  216. return 0;
  217. }
Success #stdin #stdout 0s 3076KB
stdin
Fuck you, Variadic Templates. Fuck you.
stdout
20 on the inside of a class... ?
Got myself a 20 !
Now _I_ Got myself a 20 !
Now _I_ Got myself a 20 !
Dat Multi Member Function: Bark Bark | Meow Meow
Dat Static Multi Function: Bahh Bahh | Moo Moo