Pergunta

I am trying to create a very simple event system to be used in a game. I have a EventManager class that looks something like this:

typedef std::function<void(IEvent* event)> CallbackType;

class EventManager
{
public:
    void AddListener(const std::string eventName, IEventListener* listener)
    {
        CallbackType callback = std::bind(&IEventListener::HandleEvent, listener, std::placeholders::_1);

        listeners[eventName].push_back(callback);
    }

    void AddListener(const std::string eventName, CallbackType callback)
    {
        // ...
    }

    void TriggerEvent(IEvent* event)
    {
        for (CallbackType callback : listeners[event->GetName()])
        {
            callback(event);
        }
    }
private:
    std::map<std::string, std::vector<CallbackType>> listeners;
}

The 1st AddListener function works perfectly. The TriggerEvent function calls the HandleEvent function, which is implemented by each class that extends my IEventListener interface.

I would really like to be able to pass a callback to the 2nd AddListener function. This callback would then get called in the TriggerEvent function as before. I can pass in a callback constructed using std::bind and this works. For example:

eventManager->AddListener("WindowResize", std::bind(&MyClass::MemberFunction, this, std::placeholders::_1));

where MyClass extends the IEventListener interface. However, I'd really like to be able to just pass a simple function pointer instead:

eventManager->AddListener("WindowResize", this, &MyClass::MemberFunction);

Is this possible?

Edit

For anyone interested, I wrote a couple of macros that I think makes things a little cleaner.

#define MEMBER_CALLBACK(funPtr) \
std::bind(&funPtr, this, std::placeholders::_1)

#define MEMBER_CALLBACK_WITH_INSTANCE(funPtr, instancePtr) \
std::bind(&funPtr, instancePtr, std::placeholders::_1)

Now I can subscribe to an event by:

eventManager->AddListener("EventName", MEMBER_CALLBACK(MyClass::MemberFunction));
Foi útil?

Solução

You can't pass a simple function pointer because MyClass::MemberFunction isn't a simple function. The std::bind() works because it associates an instance of MyClass with the reference to the member function. Without that information, the member function would not have access to the instance's data.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top