Is there a better way to return the same string literal from both a static and non-static function?

My C ++ is pretty rusty, and generics always confuse me, so the combination is not very good for my brain, so here is my problem.

I have a set of classes that will look like this:

class MyEvent2 : public Event { public: static constexpr char* CLASS_NAME = "MyEvent2"; MyEvent2(Object& sender) : Event(sender) { } virtual ~MyEvent2() {} static const char* EventId() { return MyEvent2::CLASS_NAME; } const char* eventId() override { return MyEvent2::CLASS_NAME; } }; 

Classes will be used to register event handlers on the event bus, so I will add such handlers.

  EventBus::AddHandler<MyEvent>(*this); EventBus::AddHandler<MyEvent2>(*this); 

then I create event events and fire them like this:

 MyEvent e1(*this); MyEvent2 e2(*this); EventBus::FireEvent(e1); EventBus::FireEvent(e2); 

My question is, how do I do this general? I would like to be able to create some derived event class, where I just need to include one line, which really needs to be unique.

 static constexpr char* CLASS_NAME = "TheClassName"; 

btw: I know it can use typeid to get something like this, but I can't use it on Arduino devices.

and then add unique fields and event elements.

Here is what I have done so far:

I created a template class (or should it be called a class template?):

 template<class T> class ArduinoEvent : public Event { public: T(Object& sender) : Event(sender) { } virtual ~T() {} static const char* EventId() { return T::CLASS_NAME; } const char* eventId() override { return T::CLASS_NAME; } }; 

But I'm not sure how to use it, or if it's even the right direction.

+7
c ++ templates
source share
1 answer

You can try with Curiosly Recurring Pattern (CRTP) . It would look like this:

 template <typename T> class BaseEvent : public Event { public: static constexpr const char* id = T::CLASS_NAME; constexpr const char* eventId() const { return T::CLASS_NAME; } }; 

The template will then be used to create new event classes as follows:

 class MyEvent1 : public BaseEvent<MyEvent1> { public: static constexpr const char* CLASS_NAME = "MyEvent1"; }; class MyEvent2 : public BaseEvent<MyEvent2> { public: static constexpr const char* CLASS_NAME = "MyEvent2"; }; 

Then you can use these classes as expected:

 int main() { MyEvent1 e1; cout << e1.eventId() << ", " << MyEvent1::id << endl; MyEvent2 e2; cout << e2.eventId() << ", " << MyEvent2::id << endl; return 0; } 

You can verify that eventId() behaves as expected in this online example ). Note that the BaseEvent template must inherit from Event if you want to handle all events in a polymorphic way.

+8
source share

All Articles