fork download
  1. #include <iostream>
  2. #include <map>
  3. #include <vector>
  4.  
  5. /**
  6.   * Receiver
  7.   */
  8. class EBaseReceiver
  9. {
  10. protected:
  11. static std::size_t nextId;
  12. };
  13.  
  14. template <class TEventData>
  15. class Receiver : public EBaseReceiver
  16. {
  17. friend class EventManager;
  18. public:
  19. virtual void onEventReceive( const TEventData& event ) = 0;
  20. static std::size_t getId() { return ID; }
  21. private:
  22. static std::size_t ID;
  23. };
  24.  
  25. /**
  26. * Event
  27. */
  28. struct BaseEvent
  29. {
  30. protected:
  31. static std::size_t nextId;
  32. };
  33.  
  34. template <typename T>
  35. struct Event : public BaseEvent
  36. {
  37. static std::size_t getId() { return ID; }
  38. static std::size_t ID;
  39. };
  40.  
  41. /**
  42. * EventManager
  43. */
  44. class EventManager
  45. {
  46. private:
  47.  
  48. typedef std::vector<EBaseReceiver*> ReceiverArray;
  49. typedef std::map<std::size_t, ReceiverArray> ImplSubscriberArray;
  50. ImplSubscriberArray subscribers;
  51.  
  52. public:
  53.  
  54. template< class TEvent, template<class> class TReceiver>
  55. void subscribe( TReceiver<TEvent>* receiver )
  56. {
  57. const std::size_t eventId = TEvent::getId();
  58. this->subscribers[eventId].push_back(receiver);
  59. }
  60.  
  61. template <typename TEvent>
  62. void emit( const TEvent& event )
  63. {
  64. const ReceiverArray& receivers = this->subscribers[TEvent::getId()];
  65. for( auto& receiver : receivers )
  66. {
  67. static_cast<Receiver<TEvent>&>((*receiver)).onEventReceive(event);
  68. }
  69. }
  70. };
  71.  
  72. /**
  73. * Test events
  74. */
  75. EventManager eventManager;
  76. struct HealthEvent : public Event<HealthEvent>{};
  77. struct DamageEvent : public Event<DamageEvent>{};
  78.  
  79. /**
  80. * Test classes
  81. */
  82. class DamageSystem : public Receiver<HealthEvent>, public Receiver<DamageEvent>
  83. {
  84. public:
  85. DamageSystem() : Receiver<HealthEvent>(), Receiver<DamageEvent>()
  86. {
  87. eventManager.subscribe<HealthEvent, ::Receiver>(this);
  88. eventManager.subscribe<DamageEvent, ::Receiver>(this);
  89. }
  90.  
  91. void onEventReceive( const HealthEvent& event ) { std::cout << "HealthEvent !" << std::endl; };
  92. void onEventReceive( const DamageEvent& event ) { std::cout << "DamageEvent !" << std::endl; };
  93. };
  94.  
  95. int main()
  96. {
  97. DamageSystem system;
  98. eventManager.emit(DamageEvent());
  99. return 0;
  100. }
  101.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
/home/ArxV62/cclQzaN1.o: In function `void EventManager::emit<DamageEvent>(DamageEvent const&)':
prog.cpp:(.text._ZN12EventManager4emitI11DamageEventEEvRKT_[_ZN12EventManager4emitI11DamageEventEEvRKT_]+0x11): undefined reference to `Event<DamageEvent>::ID'
/home/ArxV62/cclQzaN1.o: In function `void EventManager::subscribe<DamageEvent, Receiver>(Receiver<DamageEvent>*)':
prog.cpp:(.text._ZN12EventManager9subscribeI11DamageEvent8ReceiverEEvPT0_IT_E[_ZN12EventManager9subscribeI11DamageEvent8ReceiverEEvPT0_IT_E]+0x11): undefined reference to `Event<DamageEvent>::ID'
/home/ArxV62/cclQzaN1.o: In function `main':
prog.cpp:(.text.startup+0x1e): undefined reference to `Event<HealthEvent>::ID'
collect2: error: ld returned 1 exit status
stdout
Standard output is empty