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, std::forward<Args>(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& right) const {
  28. return obj == right.obj && func == right.func;
  29. }
  30. bool operator!= (const Callback& 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)(std::forward<Args>(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)(std::forward<Args>(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](std::forward<T1>(t1)...);
  99. }
  100.  
  101. void operator()(T1... t1) {
  102. Invoke(std::forward<T1>(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. struct MoveableOnly
  125. {
  126. MoveableOnly() = default;
  127. MoveableOnly(MoveableOnly const&) = delete;
  128. MoveableOnly(MoveableOnly&&) = default;
  129. MoveableOnly& operator=(MoveableOnly const&) = delete;
  130. MoveableOnly& operator=(MoveableOnly&&) = default;
  131. };
  132.  
  133. namespace Static {
  134. void Test1(int num) { std::cout << "Static: " << num << "!" << std::endl; }
  135. void Test9(MoveableOnly&& m) { std::cout << "Static: MoveableOnly !" << std::endl; }
  136. }
  137. struct Sink {
  138. void Test1(int num) { std::cout << num << " member function" << std::endl; }
  139. void Test2(std::string s, double d)
  140. { std::cout << s << d << " member function" << std::endl; }
  141. static void Test3(int snum) { std::cout << snum << " static member" << std::endl; }
  142. };
  143.  
  144. int main(int argc, char* argv[]) {
  145. Event<int> intev;
  146. Sink sink;
  147. int count = 20;
  148. intev(count++); intev.Add<Sink, &Sink::Test1>(sink);
  149.  
  150. intev(count++); intev.Add<&Static::Test1>();
  151. intev(count++); intev.Add<&Static::Test1>();
  152. intev(count++); intev.Add<&Static::Test1>();
  153.  
  154. intev(count++); assert(intev.Remove<&Static::Test1>());
  155. intev(count++); assert(intev.Remove<&Static::Test1>());
  156. intev(count++); assert(intev.Remove<&Static::Test1>());
  157.  
  158. assert(!intev.Remove<&Static::Test1>());
  159.  
  160. intev(count++); intev.Remove<Sink, &Sink::Test1>(sink);
  161. intev(count++);
  162.  
  163. Event<std::string, double> complex_ev;
  164. complex_ev.Add<Sink, &Sink::Test2>(sink);
  165.  
  166. complex_ev("hello world: ", 42.31415926);
  167.  
  168. Event<MoveableOnly&&> movev;
  169. movev.Add<&Static::Test9>();
  170.  
  171. movev(MoveableOnly()); // I think MSVC had a bug that requires std::move here, too?
  172.  
  173. MoveableOnly arg;
  174. movev(std::move(arg));
  175. }
Compilation error #stdin compilation error #stdout 0s 3024KB
stdin
Standard input is empty
compilation info
prog.cpp:130:52: error: 'MoveableOnly& MoveableOnly::operator=(MoveableOnly&&)' cannot be defaulted
stdout
Standard output is empty