My c++ is pretty rusty and generics always confuse me anyway, so the combination is not good for my brain, so here is my problem.
I have a set of classes that are all going to 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;
}
};
The classes will be used to register event handlers on an event bus, so I add the handlers like so.
EventBus::AddHandler<MyEvent>(*this);
EventBus::AddHandler<MyEvent2>(*this);
then I create intances of the events and fire them like this:
MyEvent e1(*this);
MyEvent2 e2(*this);
EventBus::FireEvent(e1);
EventBus::FireEvent(e2);
My question is how do I make this generic? I would like to be able to make some derived "Event" class where I just need to include the one line that really needs to be unique
static constexpr char* CLASS_NAME = "TheClassName";
btw: I know could use typeid to get something like this, but I can't use it on Arduino devices.
and then add unique "Event" specific fields and members.
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 am not sure how to use this or if this is even the right direction.
Static member functions are allowed to access only the static data members or other static member functions, they can not access the non-static data members or member functions of the class.
A non-static member function is a function that is declared in a member specification of a class without a static or friend specifier. ( see static member functions and friend declaration for the effect of those keywords)
A static member function can be called even if no objects of the class exist and the static functions are accessed using only the class name and the scope resolution operator ::. A static member function can only access static data member, other static member functions and any other functions from outside the class.
You could try with Curiosly Recurring Pattern (CRTP). It would look something like following :
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 would then be used to instantiate 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";
};
You could then 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 check that eventId()
behaves as expected in this online example). Note that the template BaseEvent
needs to inherit from Event
if you want to handle all events in a polymorphic way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With