Reputation: 361
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!
Upvotes: 0
Views: 1139
Reputation: 16266
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.
Upvotes: 4