简体   繁体   中英

How to use std::bind for adding member callback to a messenger system

I am currently trying to implement a messenger system for my game engine. It uses function callbacks of the form:

typedef std::function<void(const Message &)> Callback;

I want all objects to be able to subscribe to a message of a specific type (where the type is just a string). Subscribing means adding their "onEvent" function to the dictionary of callbacks.

mutable std::map<std::string, std::vector<Callback>> callbackDictionary;

The update function then calls these functions and passes the according message (from which the "onEvent" functions can get their data)

for each (auto message in messageList)
{
    // find the list of respective callbacks
    auto it = callbackDictionary.find(message->GetType());

    // If there are callbacks registered for this message type
    if (it != callbackDictionary.end())
    {
        // call every registred callback with the appropreate message
        for each (auto callback in it->second)
            callback(*message);
    }
}

Now, my problem is that I am not quite sure how to bind these "onEvent" functions. I have just recently switched to C++11 and the concept of function objects and std::bind is quite new to me. So here is what I have tried:

messageBus.Subscribe("Message/Click",std::bind(&ClickableComponent::OnClick, this));

where the ClickableComponent::OnClick function has the required signature:

void OnClick(const Message &);

and the Subscribe function just adds the passed function to the dictionary

void Messenger::Subscribe(std::string type, Callback callbackFunction) const
{
    callbackDictionary[type].push_back(callbackFunction);
}

(The push_back is used because there is a vector of callbacks for each type)

The code seems fine to me but the line:

messageBus.Subscribe("Message/Click", std::bind(&ClickableComponent::OnClick, this));

Gives me the error: picture of the error discription

I have tried all kinds of stuff like forwarding the Messenger reference and using placeholders, but I have the feeling that I am doing something else wrong. Also, better idea on how to implement this messenger system are appreciated ^^

Thanks for your help!

std::bind is not necessary in your case, lambda function would do just fine:

messageBus.Subscribe("Message/Click", [this](const Message& msg) { OnClick(msg); });

std::bind is more useful in specific cases of metaprogramming.

But if you're curios enough to see how to use std::bind :

messageBus.Subscribe("Message/Click", 
    std::bind(&ClickableComponent::OnClick, this, std::placeholders::_1));

Here, as you see, you missed std::placeholders::_1 . Your functor signature is void(const Message&) , but you try to store a member function which signature can be regarded as void(ClickableComponent*, const Message&) . To partially apply some arguments (what std::bind does) you need to specify arguments that you'd like to bind and arguments that you leave unbound.

Lambda is preferred because usually it's shorted, more flexible and more readable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM