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