The question is strictly about std::function
and not boost::function
. See the Update section at the bottom of this question for more details, especially the part about it not being possible to compare non-empty std::function
objects per the C++11 standard.
The C++11 std::function
class template is great for maintaining a collection of callbacks. One can store them in a vector
, for example and invoke them when need be. However, maintaining these objects and allowing for unregistration seems to be impossible.
Let me be specific, imagine this class:
class Invoker
{
public:
void Register(std::function<void()> f);
void Unregister(std::function<void()> f);
void InvokeAll();
private:
// Some container that holds the function objects passed to Register()
};
Sample usage scenario:
void foo()
{
}
int main()
{
std::function<void()> f1{foo};
std::function<void()> f2{[] {std::cout << "Hello\n";} };
Invoker inv;
// The easy part
// Register callbacks
inv.Register(f1);
inv.Register(f2);
// Invoke them
inv.InvokeAll();
// The seemingly impossible part. How can Unregister() be implemented to actually
// locate the correct object to unregister (i.e., remove from its container)?
inv.Unregister(f2);
inv.Unregister(f1);
}
It is fairly clear how the Register()
function can be implemented. However, how would one go about implementing Unregister()
. Let's say that the container that holds the function objects is vector<std::function<void()>>
. How would you find a particular function object that is passed to the Unregister()
call? std::function
does supply an overloaded operator==
, but that only tests for an empty function object (i.e., it cannot be used to compare two non-empty function objects to see if they both refer to the same actual invocation).
I would appreciate any ideas.
Update:
Ideas so far mainly consist of the addition of a cookie to be associated with each std::function
object that can be used to unregister it. I was hoping for something that is not exogenous to the std::function
object itself. Also, there seems to be much confusion between std::function
and boost::function
. The question is strictly about std::function
objects, and not boost::function
objects.
Also, you cannot compare two non-empty std::function
objects for equality. They will always compare non-equal per the standard. So, links in the comments to solutions that do just that (and use boost::function
objects to boot) are patently wrong in the context of this question.