fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4.  
  5. const static auto null = 0;
  6.  
  7. template<typename TFuncSignature>
  8. class Callback;
  9.  
  10. /////////////////
  11. /* 0 ARGUMENTS */
  12. /////////////////
  13.  
  14. template<typename R>
  15. class Callback<R ()> {
  16. public:
  17. typedef R (*TFunc)(void*);
  18.  
  19. const static size_t Arity = 0;
  20.  
  21. Callback() : obj(0), func(0) {}
  22. Callback(void* o, TFunc f) : obj(o), func(f) {}
  23.  
  24. R operator()( ) const {
  25. return (*func)(obj);
  26. }
  27.  
  28. typedef void* Callback::*SafeBoolType;
  29. operator SafeBoolType () const {
  30. return func != 0? &Callback::obj : 0;
  31. }
  32.  
  33. bool operator! () const {
  34. return func == 0;
  35. }
  36.  
  37. bool operator== ( const Callback<R ()>& right ) const {
  38. return obj == right.obj && func == right.func;
  39. }
  40.  
  41. bool operator!= ( const Callback<R ()>& right ) const {
  42. return obj != right.obj || func != right.func;
  43. }
  44.  
  45. private:
  46. void* obj;
  47. TFunc func;
  48. };
  49.  
  50. namespace detail {
  51. template<typename R, class T>
  52. struct DeduceConstMemCallback0 {
  53. template<R(T::*Func)() const> inline static Callback<R()> Bind(T* o) {
  54. struct _ { static R wrapper(void* o) { return (static_cast<T*>(o)->*Func)(); } };
  55. return Callback<R()>(o, (R(*)(void*)) _::wrapper);
  56. }
  57. };
  58.  
  59. template<typename R, class T>
  60. struct DeduceMemCallback0 {
  61. template<R(T::*Func)()> inline static Callback<R()> Bind(T* o) {
  62. struct _ { static R wrapper(void* o) { return (static_cast<T*>(o)->*Func)(); } };
  63. return Callback<R()>(o, (R(*)(void*)) _::wrapper);
  64. }
  65. };
  66.  
  67. template<typename R>
  68. struct DeduceStaticCallback0 {
  69. template<R(*Func)()> inline static Callback<R()> Bind() {
  70. struct _ { static R wrapper(void* ) { return (*Func)(); } };
  71. return Callback<R()>(0, (R(*)(void*)) _::wrapper);
  72. }
  73. };
  74. }
  75.  
  76. template<typename R, class T>
  77. detail::DeduceConstMemCallback0<R, T> DeduceCallback0( R(T::*)() const ) {
  78. return detail::DeduceConstMemCallback0<R, T>();
  79. }
  80.  
  81. template<typename R, class T>
  82. detail::DeduceMemCallback0<R, T> DeduceCallback0(R(T::*)()) {
  83. return detail::DeduceMemCallback0<R, T>();
  84. }
  85.  
  86. template<typename R>
  87. detail::DeduceStaticCallback0<R> DeduceCallback0(R(*)()) {
  88. return detail::DeduceStaticCallback0<R>();
  89. }
  90.  
  91. class EventBase {
  92. public:
  93. const static int ExpectedFunctorCount = 2;
  94. };
  95.  
  96. class Event {
  97. public:
  98. typedef void(* TSignature)( );
  99. typedef Callback<void( )> TCallback;
  100. typedef std::vector<TCallback> InvocationTable;
  101.  
  102. protected:
  103. InvocationTable invocations;
  104.  
  105. public:
  106. const static int ExpectedFunctorCount = 2;
  107.  
  108. Event () : invocations() {
  109. invocations.reserve( ExpectedFunctorCount );
  110. }
  111.  
  112. Event ( int expectedfunctorcount ) : invocations() {
  113. invocations.reserve( expectedfunctorcount );
  114. }
  115.  
  116. template <void (* TFunc)( )> void Add ( ) {
  117. TCallback c = DeduceCallback0( TFunc ).template Bind< TFunc >( );
  118. invocations.push_back( c );
  119. }
  120.  
  121. template <typename T, void (T::* TFunc)( )> void Add ( T& object ) {
  122. Add<T, TFunc>( &object );
  123. }
  124.  
  125. template <typename T, void (T::* TFunc)( )> void Add ( T* object ) {
  126. TCallback c = DeduceCallback0( TFunc ).template Bind< TFunc >( object );
  127. invocations.push_back( c );
  128. }
  129.  
  130. template <typename T, void (T::* TFunc)( ) const> void Add ( T& object ) {
  131. Add<T, TFunc>( &object );
  132. }
  133.  
  134. template <typename T, void (T::* TFunc)( ) const> void Add ( T* object ) {
  135. TCallback c = DeduceCallback0( TFunc ).template Bind< TFunc >( object );
  136. invocations.push_back( c );
  137. }
  138.  
  139. void Invoke ( ) {
  140. size_t i;
  141. for ( i = 0; i < invocations.size(); ++i ) {
  142. invocations[i]( );
  143. }
  144. }
  145.  
  146. void operator() ( ) {
  147. Invoke( );
  148. }
  149.  
  150. size_t InvocationCount ( ) {
  151. return invocations.size( );
  152. }
  153.  
  154. template <void (* TFunc)( )> bool Remove ()
  155. { return Remove (DeduceCallback0(TFunc).template Bind<TFunc>()); }
  156.  
  157. template <typename T, void (T::* TFunc)( )> bool Remove (T& object)
  158. { return Remove <T, TFunc>(&object); }
  159. template <typename T, void (T::* TFunc)( )> bool Remove (T* object)
  160. { return Remove (DeduceCallback0(TFunc).template Bind<TFunc>(object)); }
  161.  
  162. template <typename T, void (T::* TFunc)( ) const> bool Remove (T& object)
  163. { return Remove <T, TFunc>(&object); }
  164. template <typename T, void (T::* TFunc)( ) const> bool Remove (T* object)
  165. { return Remove (DeduceCallback0(TFunc).template Bind<TFunc>(object)); }
  166.  
  167. protected:
  168.  
  169. bool Remove( TCallback const& target ) {
  170. auto it = std::find(invocations.begin(), invocations.end(), target);
  171. if ( it == invocations.end() )
  172. return false;
  173. invocations.erase( it );
  174. return true;
  175. }
  176.  
  177. };
  178.  
  179. void Arf () {
  180. std::cout << "Puppy Static Function" << std::endl;
  181. }
  182.  
  183. struct Robot {
  184. void Beep () {
  185. std::cout << "RoZ Beep() Member Function" << std::endl;
  186. }
  187.  
  188. void operator() () {
  189. std::cout << "RoZ Operator() Member Function" << std::endl;
  190. }
  191. };
  192.  
  193. int main(int argc, char* argv[]) {
  194. Event ev;
  195. int i = 500;
  196. auto a = [] () {
  197. std::cout << "Lambda me baby!" << std::endl;
  198. };
  199. typedef decltype( a ) alambda;
  200. auto b = [&i] () {
  201. std::cout << "Lambda's captured my " << i << "<3!" << std::endl;
  202. };
  203. typedef decltype( b ) blambda;
  204. i = 600;
  205.  
  206. void( * funcpointer )() = null;
  207. void( Robot::* robotmemfuncpointer )() = null;
  208. // No good, operator() is const ( Why ? )
  209. //void( blambda::* memfuncpointer )() const = null;
  210. void( alambda::* amemfuncpointer )() const = null;
  211. void( blambda::* bmemfuncpointer )() const = null;
  212.  
  213. funcpointer = a;
  214. robotmemfuncpointer = &Robot::operator();
  215. amemfuncpointer = &alambda::operator();
  216. bmemfuncpointer = &blambda::operator();
  217.  
  218. std::cout <<
  219. "===========================================================\n" <<
  220. "Calling Lambdas statically, using Member Function Pointers\n" <<
  221. "===========================================================\n" <<
  222. std::endl;
  223. (a.*amemfuncpointer)();
  224. (b.*bmemfuncpointer)();
  225.  
  226. std::cout <<
  227. "===============================================================\n" <<
  228. "Calling Lambdas through Callback, because I can, Mother Fucker.\n" <<
  229. "I will also change a captured-by-value integer on the lambda...\n" <<
  230. " because I can, Mother Fucker!\n" <<
  231. "===============================================================\n" <<
  232. std::endl;
  233.  
  234. i = 200;
  235. ev.Add<alambda, &alambda::operator()>( a );
  236. ev.Add<blambda, &blambda::operator()>( b );
  237. ev();
  238.  
  239. ev.Remove<blambda, &blambda::operator()>( b );
  240. ev();
  241. // Doesn't remove alambda, it's unique!
  242. ev.Remove<blambda, &blambda::operator()>( b );
  243. ev();
  244. // Now removes alambda
  245. ev.Remove<alambda, &alambda::operator()>( a );
  246. ev();
  247.  
  248. return 0;
  249. }
Success #stdin #stdout 0s 3064KB
stdin
GO GO WORK WORK GO DO IT I CAN BELIEVE IN YOOOU!
stdout
===========================================================
Calling Lambdas statically, using Member Function Pointers
===========================================================

Lambda me baby!
Lambda's captured my 600<3!
===============================================================
Calling Lambdas through Callback, because I can, Mother Fucker.
I will also change a captured-by-value integer on the lambda...
 because I can, Mother Fucker!
===============================================================

Lambda me baby!
Lambda's captured my 200<3!
Lambda me baby!
Lambda me baby!