Potat Potat - 2 months ago 21
C++ Question

std::function vs Lamda for passing member functions

I am creating a messaging system for a game engine, where in an end user of the engine can create a message object and pass it to a game object to be interpreted by listener objects contained components attached to the game object. if the message matches a message that the listener is listening for, then the listener should call a function pointer and pass it the message that was received. The basic structure looking something like this:

class Message
{
std::string message;
};

class Listener
{
std::string target;
void (*fn)(Message*);
};


with the game object's code to receive a message looking something like this:

//if the queue is empty then dont do anything
if (messageQueue.empty())
{
return;
}

//else grab the front of the queue
Message* newMessage = messageQueue.front();

//pop our message from the queue
messageQueue.pop();

//for each component in our list
for (std::vector<Component*>::iterator i = ComponentList.begin(); i < ComponentList.end(); i++)
{
Component* itemp = *i;
//for each message in its listener list
for (std::vector<Listener*>::iterator j = itemp->Listeners.begin(); j < itemp->Listeners.end(); j++)
{
Listener* jtemp = *j;
//check the listener against the newMessage
if (jtemp->name == newMessage->name)
{
//call jtemp's function
jtemp->function(newMessage);
}
}
}


the issue that I have ran into is that since the functions that need to be called by the snippet above are member functions of a component type, I cannot set
Listener.fn
to equal
Component::foo
or any other function for that matter.

I asked around my classmates to see if they could offer any advice and the two pieces of advice I received were either use lambdas or use
std::function
to convert a member function pointer into a regular function pointer.

I've never used a lambda function before, but after researching here, if I'm grasping it correctly, it seems like I would have to write a new lambda each time I pass a message which defeats the purpose of using a system like this. And after researching
std::function
here, here, and here it seems like
std::function
would give me the flexibility that I need but implementation has been giving me a large number of errors

Am I overlooking the power of lambdas, should I be using a
std::function
in this case, and if so how can a create one that returns void and takes a message pointer?

Answer

std::function is the right solution for storage. std::function stores almost anything that is compatible with its signature.

Usually you will populate it with a lambda. Because that is easier and clearer than bind or other alternatives.

std::function<void(Message*)> fn;

fn = [comp](Message * m){ comp->foo(m); };