Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

templates

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.

like image 850
nPn Avatar asked Dec 31 '17 15:12

nPn


People also ask

Can static function access non-static variables in C++?

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.

What is a non-static member function?

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)

How do you declare a static function outside class in C++?

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.


Video Answer


1 Answers

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.

like image 99
StPiere Avatar answered Oct 27 '22 18:10

StPiere