fork(1) download
  1. #include <iostream>
  2. #include <memory>
  3. #include <utility>
  4. #include <vector>
  5. #include <algorithm>
  6.  
  7. template <typename Signature>
  8. struct delegate;
  9.  
  10. template <typename... Args>
  11. struct delegate<void(Args...)>
  12. {
  13. struct base {
  14. virtual ~base() {}
  15. virtual bool do_cmp(base* other) = 0;
  16. virtual void do_call(Args... args) = 0;
  17. };
  18. template <typename T>
  19. struct call: base {
  20. T d_callback;
  21. template <typename S>
  22. call(S&& callback): d_callback(std::forward<S>(callback)) {}
  23.  
  24. bool do_cmp(base* other) {
  25. call<T>* tmp = dynamic_cast<call<T>*>(other);
  26. return tmp && this->d_callback == tmp->d_callback;
  27. }
  28. void do_call(Args... args) {
  29. return this->d_callback(std::forward<Args>(args)...);
  30. }
  31. };
  32. std::vector<std::unique_ptr<base>> d_callbacks;
  33.  
  34. delegate(delegate const&) = delete;
  35. void operator=(delegate const&) = delete;
  36. public:
  37. delegate() {}
  38. template <typename T>
  39. delegate& operator+= (T&& callback) {
  40. this->d_callbacks.emplace_back(new call<T>(std::forward<T>(callback)));
  41. return *this;
  42. }
  43. template <typename T>
  44. delegate& operator-= (T&& callback) {
  45. call<T> tmp(std::forward<T>(callback));
  46. auto it = std::remove_if(this->d_callbacks.begin(),
  47. this->d_callbacks.end(),
  48. [&](std::unique_ptr<base>& other) {
  49. return tmp.do_cmp(other.get());
  50. });
  51. this->d_callbacks.erase(it, this->d_callbacks.end());
  52. return *this;
  53. }
  54.  
  55. void operator()(Args... args) {
  56. for (auto& callback: this->d_callbacks) {
  57. callback->do_call(args...);
  58. }
  59. }
  60. };
  61.  
  62. // ----------------------------------------------------------------------------
  63.  
  64. template <typename RC, typename Class, typename... Args>
  65. class member_call {
  66. Class* d_object;
  67. RC (Class::*d_member)(Args...);
  68. public:
  69. member_call(Class* object, RC (Class::*member)(Args...))
  70. : d_object(object)
  71. , d_member(member) {
  72. }
  73. RC operator()(Args... args) {
  74. return (this->d_object->*this->d_member)(std::forward<Args>(args)...);
  75. }
  76. bool operator== (member_call const& other) const {
  77. return this->d_object == other.d_object
  78. && this->d_member == other.d_member;
  79. }
  80. bool operator!= (member_call const& other) const {
  81. return !(*this == other);
  82. }
  83. };
  84.  
  85. template <typename RC, typename Class, typename... Args>
  86. member_call<RC, Class, Args...> mem_call(Class& object,
  87. RC (Class::*member)(Args...)) {
  88. return member_call<RC, Class, Args...>(&object, member);
  89. }
  90.  
  91. // ----------------------------------------------------------------------------
  92.  
  93. void foobar(int number) { std::cout << "foobar(" << number << ")\n"; }
  94.  
  95. // ----------------------------------------------------------------------------
  96.  
  97. int main()
  98. {
  99. delegate<void(int)> testDel;
  100.  
  101. testDel += foobar;
  102.  
  103. testDel(5);
  104. }
Success #stdin #stdout 0s 3476KB
stdin
Standard input is empty
stdout
foobar(5)