fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <cassert>
  5.  
  6. template<typename TFuncSignature>
  7. class Callback;
  8.  
  9. template<typename R, typename... Args>
  10. class Callback<R(Args...)> {
  11. public:
  12. typedef R(*TFunc)(void*, Args...);
  13.  
  14. Callback() : obj(0), func(0) {}
  15. Callback(void* o, TFunc f) : obj(o), func(f) {}
  16.  
  17. R operator()(Args... a1) const {
  18. return (*func)(obj, a1...);
  19. }
  20. typedef void* Callback::*SafeBoolType;
  21. operator SafeBoolType() const {
  22. return func? &Callback::obj : 0;
  23. }
  24. bool operator!() const {
  25. return func == 0;
  26. }
  27. bool operator== (const Callback<R(Args...)>& right) const {
  28. return obj == right.obj && func == right.func;
  29. }
  30. bool operator!= (const Callback<R(Args...)>& right) const {
  31. return obj != right.obj || func != right.func;
  32. }
  33. private:
  34. void* obj;
  35. TFunc func;
  36. };
  37.  
  38. namespace detail
  39. {
  40. template<typename R, class T, typename... Args>
  41. struct DeduceMemCallback {
  42. template<R(T::*Func)(Args...)> inline static Callback<R(Args...)> Bind(T* o) {
  43. struct _ { static R wrapper(void* o, Args... a1) { return (static_cast<T*>(o)->*Func)(a1...); } };
  44. return Callback<R(Args...)>(o, (R(*)(void*, Args...)) _::wrapper);
  45. }
  46. };
  47.  
  48. template<typename R, typename... Args>
  49. struct DeduceStaticCallback {
  50. template<R(*Func)(Args...)> inline static Callback<R(Args...)> Bind() {
  51. struct _ { static R wrapper(void*, Args... a1) { return (*Func)(a1...); } };
  52. return Callback<R(Args...)>(0, (R(*)(void*, Args...)) _::wrapper);
  53. }
  54. };
  55. }
  56.  
  57. template<typename R, class T, typename... Args>
  58. detail::DeduceMemCallback<R, T, Args...> DeduceCallback(R(T::*)(Args...)) {
  59. return detail::DeduceMemCallback<R, T, Args...>();
  60. }
  61.  
  62. template<typename R, typename... Args>
  63. detail::DeduceStaticCallback<R, Args...> DeduceCallback(R(*)(Args...)) {
  64. return detail::DeduceStaticCallback<R, Args...>();
  65. }
  66.  
  67. template <typename... T1> class Event {
  68. public:
  69. typedef void(*TSignature)(T1...);
  70. typedef Callback<void(T1...)> TCallback;
  71.  
  72. protected:
  73. typedef std::vector<TCallback> Table;
  74. Table invocations;
  75.  
  76. public:
  77. const static int ExpectedFunctorCount = 2;
  78.  
  79. Event() : invocations() {
  80. invocations.reserve(ExpectedFunctorCount);
  81. }
  82.  
  83. template <void (* TFunc)(T1...)> void Add() {
  84. TCallback c = DeduceCallback(TFunc).template Bind<TFunc>();
  85. invocations.push_back(c);
  86. }
  87.  
  88. template <typename T, void (T::* TFunc)(T1...)> void Add(T& object) {
  89. Add<T, TFunc>(&object);
  90. }
  91.  
  92. template <typename T, void (T::* TFunc)(T1...)> void Add(T* object) {
  93. TCallback c = DeduceCallback(TFunc).template Bind<TFunc>(object);
  94. invocations.push_back(c);
  95. }
  96.  
  97. void Invoke(T1... t1) {
  98. for(size_t i = 0; i < invocations.size() ; ++i) invocations[i](t1...);
  99. }
  100.  
  101. void operator()(T1... t1) {
  102. Invoke(t1...);
  103. }
  104.  
  105. size_t InvocationCount() { return invocations.size(); }
  106.  
  107. template <void (* TFunc)(T1...)> bool Remove ()
  108. { return Remove (DeduceCallback(TFunc).template Bind<TFunc>()); }
  109. template <typename T, void (T::* TFunc)(T1...)> bool Remove (T& object)
  110. { return Remove <T, TFunc>(&object); }
  111. template <typename T, void (T::* TFunc)(T1...)> bool Remove (T* object)
  112. { return Remove (DeduceCallback(TFunc).template Bind<TFunc>(object)); }
  113.  
  114. protected:
  115. bool Remove(TCallback const& target) {
  116. auto it = std::find(invocations.begin(), invocations.end(), target);
  117. if (it==invocations.end())
  118. return false;
  119. invocations.erase(it);
  120. return true;
  121. }
  122. };
  123.  
  124. namespace Static {
  125. void Test1(int num) { std::cout << "Static: " << num << " !" << std::endl; }
  126. }
  127. struct Sink {
  128. void Test1(int num) { std::cout << num << " member function" << std::endl; }
  129. void Test2(std::string s, double d)
  130. { std::cout << s << d << " member function" << std::endl; }
  131. static void Test3(int snum) { std::cout << snum << " static member" << std::endl; }
  132. };
  133.  
  134. int main(int argc, char* argv[]) {
  135. Event<int> intev;
  136. Sink sink;
  137. int count = 20;
  138. intev(count++); intev.Add<Sink, &Sink::Test1>(sink);
  139.  
  140. intev(count++); intev.Add<&Static::Test1>();
  141. intev(count++); intev.Add<&Static::Test1>();
  142. intev(count++); intev.Add<&Static::Test1>();
  143.  
  144. intev(count++); assert(intev.Remove<&Static::Test1>());
  145. intev(count++); assert(intev.Remove<&Static::Test1>());
  146. intev(count++); assert(intev.Remove<&Static::Test1>());
  147.  
  148. assert(!intev.Remove<&Static::Test1>());
  149.  
  150. intev(count++); intev.Remove<Sink, &Sink::Test1>(sink);
  151. intev(count++);
  152.  
  153. Event<std::string, double> complex_ev;
  154. complex_ev.Add<Sink, &Sink::Test2>(sink);
  155.  
  156. complex_ev("hello world: ", 42.31415926);
  157. }
  158.  
Success #stdin #stdout 0s 3024KB
stdin
Standard input is empty
stdout
21 member function
22 member function
Static: 22 !
23 member function
Static: 23 !
Static: 23 !
24 member function
Static: 24 !
Static: 24 !
Static: 24 !
25 member function
Static: 25 !
Static: 25 !
26 member function
Static: 26 !
27 member function
hello world: 42.3142 member function