mercredi 8 avril 2020

C++ template programming implements class member function callback

I want to implement a system similar to event distribution, but I do n’t know how to implement callbacks using template programming.

The main process is bind the class member functions that need to be callback, and then use the event enumeration to call back the registered functions.

I don't know how to write invoke callback in Manager::send?

This is my semi-finished code:

enum EventType
{
    Test1,
    Test2,
    Test3,
};

class CallbackInterface
{

};

template <typename Return, typename ...T>
class BaseCallback : public CallbackInterface
{
public:
    virtual ~BaseCallback() {}
    virtual Return operator() (T... args) = 0;
};

template <typename Object, typename Return, typename ...T>
class MemberFunctionCallback : public BaseCallback<Return, T...>
{
public:
    MemberFunctionCallback(Object* object, Return(Object::* function)(T...))
    {
        this->object = object;
        this->function = function;
    }

    virtual Return operator() (T... args)
    {
        return ((this->object)->*(this->function))(args...);
    }

private:
    Object* object;
    Return(Object::* function)(T...);
};

class Test {
public:
    void function(int i) {
        // Do something...
    }
};

class Manager {
public:
    void bind(EventType eventType, CallbackInterface* callbackInterface)
    {
        if (this->callbackMap.find(eventType) == this->callbackMap.end())
        {
            this->callbackMap[eventType] = new std::vector<CallbackInterface*>();
        }

        this->callbackMap[eventType]->push_back(callbackInterface);
    }

    template<typename ...T>
    void send(EventType eventType, T... args)
    {
        std::vector<CallbackInterface*>* list = this->callbackMap[eventType];

        for (CallbackInterface* item : list)
        {
            // Invoke callback
            // How to write here? I am not very familiar with template programming.
        }
    }

private:
    std::map<EventType, std::vector<CallbackInterface*>*> callbackMap;

};

int main() {
    Manager manager;
    Test test;

    manager.bind(EventType::Test1, new MemberFunctionCallback<Test, void, int>(&test, &Test::function));

    manager.send(EventType::Test1, 12); // Call the registered callback

    system("pause");
    return 0;
}




Aucun commentaire:

Enregistrer un commentaire