fork download
  1. #include <iostream>
  2. #include <list>
  3.  
  4. #define __EVENTLISTENERBODY(_class_) \
  5. public: virtual ~_class_() {if (m_register) *m_register = false; m_register = nullptr;} \
  6. public: void __register(bool &reg) {m_register = &reg;} \
  7. private: bool *m_register = nullptr; \
  8.  
  9. class EventResizeEventListener
  10. {
  11. __EVENTLISTENERBODY(EventResizeEventListener);
  12. public:
  13. virtual void Resize(uint32_t w, uint32_t h) = 0;
  14. };
  15.  
  16. class EventKeyListener
  17. {
  18. __EVENTLISTENERBODY(EventKeyListener);
  19. public:
  20. virtual void Key(uint32_t key, bool press) = 0;
  21. };
  22.  
  23. template<typename T, typename ... Args>
  24. class EventSignal
  25. {
  26. struct listData
  27. {
  28. void operator()(Args ...args) { (listener->*func)(args ...); }
  29.  
  30. typedef void(T::*Func)(Args ...);
  31. T *listener = nullptr;
  32. Func func;
  33. bool active = false;
  34. };
  35.  
  36. public:
  37. template <typename TypeU>
  38. void Connect(TypeU *listener, void(TypeU::*func)(Args ...))
  39. {
  40. if (!listener) return;
  41. listData data = { (T*)listener, (void(T::*)(Args...))func, true };
  42. m_lists.emplace_back(data);
  43.  
  44. auto &it = m_lists.back();
  45. listener->T::__register(it.active);
  46. }
  47.  
  48. void operator()(Args ...args) noexcept
  49. {
  50. for (auto i = m_lists.begin(); i != m_lists.end();)
  51. {
  52. if ((*i).active)
  53. {
  54. (*i)(args...);
  55. ++i;
  56. }
  57. else
  58. i = m_lists.erase(i);
  59. }
  60. }
  61.  
  62. private:
  63. std::list<listData> m_lists;
  64. };
  65.  
  66.  
  67. class FooB :
  68. public EventResizeEventListener,
  69. public EventKeyListener
  70. {
  71. public:
  72. void Resize(uint32_t w, uint32_t h) final
  73. {
  74. std::cout << w << " " << h << std::endl;
  75. }
  76.  
  77. void Key(uint32_t key, bool press) final
  78. {
  79. if (press)
  80. std::cout << key << " down" << std::endl;
  81. else
  82. std::cout << key << " up" << std::endl;
  83. }
  84. };
  85.  
  86. int main() {
  87. FooB *fff = new FooB;
  88.  
  89. EventSignal<EventResizeEventListener, uint32_t, uint32_t> sigResize;
  90. EventSignal<EventKeyListener, uint32_t, bool> sigKey;
  91.  
  92. sigResize.Connect(fff, &FooB::Resize);
  93. sigKey.Connect(fff, &FooB::Key);
  94.  
  95. sigResize(10, 20);
  96. sigKey(10, true);
  97.  
  98. delete fff; fff = nullptr;
  99.  
  100. sigResize(40, 50);
  101. sigKey(10, false);
  102.  
  103. return 0;
  104. }
Success #stdin #stdout 0s 4536KB
stdin
Standard input is empty
stdout
10 20
10 down