fork(1) download
  1. #include <type_traits>
  2. #include <functional>
  3. #include <algorithm>
  4. #include <stdexcept>
  5. #include <iostream>
  6. #include <typeinfo>
  7. #include <utility>
  8. #include <ostream>
  9. #include <vector>
  10. #include <string>
  11.  
  12. using namespace std;
  13.  
  14. // _____________________________Implementation__________________________________________
  15.  
  16. #define USE_VARIADIC_TEMPLATES 0
  17.  
  18. template<typename Callback,typename Function>
  19. bool func_compare(const Function &lhs,const Function &rhs)
  20. {
  21. typedef typename conditional<is_function<Callback>::value,typename add_pointer<Callback>::type,Callback>::type request_type;
  22. if (const request_type* lhs_internal = lhs.template target<request_type>())
  23. if (const request_type* rhs_internal = rhs.template target<request_type>())
  24. return *rhs_internal == *lhs_internal;
  25. return false;
  26. }
  27.  
  28. #if USE_VARIADIC_TEMPLATES
  29. #define FUNC_SIG_TYPES typename ...Args
  30. #define FUNC_SIG_TYPES_PASS Args...
  31. #else
  32. #define FUNC_SIG_TYPES typename function_signature
  33. #define FUNC_SIG_TYPES_PASS function_signature
  34. #endif
  35.  
  36. template<FUNC_SIG_TYPES>
  37. struct function_comparable: function<FUNC_SIG_TYPES_PASS>
  38. {
  39. typedef function<FUNC_SIG_TYPES_PASS> Function;
  40. bool (*type_holder)(const Function &,const Function &);
  41. public:
  42. function_comparable(){}
  43. template<typename Func>
  44. function_comparable(Func f_)
  45. : Function(f_), type_holder(func_compare<Func,Function>)
  46. {
  47. }
  48. template<typename Func>
  49. function_comparable &operator=(Func f_)
  50. {
  51. Function::operator=(f_);
  52. type_holder=func_compare<Func,Function>;
  53. return *this;
  54. }
  55. friend bool operator==(const Function &lhs,const function_comparable &rhs)
  56. {
  57. return rhs.type_holder(lhs,rhs);
  58. }
  59. friend bool operator==(const function_comparable &lhs,const Function &rhs)
  60. {
  61. return rhs==lhs;
  62. }
  63. friend void swap(function_comparable &lhs,function_comparable &rhs)// noexcept
  64. {
  65. lhs.swap(rhs);
  66. lhs.type_holder.swap(rhs.type_holder);
  67. }
  68. };
  69.  
  70. // ________________________________Example______________________________________________
  71.  
  72. typedef void (function_signature)();
  73.  
  74. void func1()
  75. {
  76. cout << "func1" << endl;
  77. }
  78.  
  79. void func3()
  80. {
  81. cout << "func3" << endl;
  82. }
  83.  
  84. class func2
  85. {
  86. int data;
  87. public:
  88. explicit func2(int n) : data(n) {}
  89. friend bool operator==(const func2 &lhs,const func2 &rhs)
  90. {
  91. return lhs.data==rhs.data;
  92. }
  93. void operator()()
  94. {
  95. cout << "func2, data=" << data << endl;
  96. }
  97. };
  98. struct Caller
  99. {
  100. template<typename Func>
  101. void operator()(Func f)
  102. {
  103. f();
  104. }
  105. };
  106. class Callbacks
  107. {
  108. vector<function<function_signature>> v;
  109. public:
  110. void register_callback_comparator(function_comparable<function_signature> callback)
  111. {
  112. v.push_back(callback);
  113. }
  114. void register_callback(function<function_signature> callback)
  115. {
  116. v.push_back(callback);
  117. }
  118. void unregister_callback(function_comparable<function_signature> callback)
  119. {
  120. auto it=find(v.begin(),v.end(),callback);
  121. if(it!=v.end())
  122. v.erase(it);
  123. else
  124. throw runtime_error("not found");
  125. }
  126. void call_all()
  127. {
  128. for_each(v.begin(),v.end(),Caller());
  129. cout << string(16,'_') << endl;
  130. }
  131. };
  132.  
  133. int main()
  134. {
  135. Callbacks cb;
  136. function_comparable<function_signature> f;
  137. f=func1;
  138. cb.register_callback_comparator(f);
  139.  
  140. cb.register_callback(func2(1));
  141. cb.register_callback(func2(2));
  142. cb.register_callback(func3);
  143. cb.call_all();
  144.  
  145. cb.unregister_callback(func2(2));
  146. cb.call_all();
  147. cb.unregister_callback(func1);
  148. cb.call_all();
  149. }
  150.  
Success #stdin #stdout 0s 3068KB
stdin
Standard input is empty
stdout
func1
func2, data=1
func2, data=2
func3
________________
func1
func2, data=1
func3
________________
func2, data=1
func3
________________