stack user stack user - 2 months ago 38
C++ Question

remove an item from a vector of std::function

I'm attempting to write a an observer pattern in c++
so I have a map that contains eventname -> vector of callback functions

The callback functions are stored in a vector as

std::function<void(void *)>


so the map looks like

std::unordered_map<std::string, std::vector<std::function<void(void *)>>>


I can add listeners to the vector and receive and respond to event notifications. My problem is with implementing detach.

So std::function's can't be compared, so erase/remove is out, so I wanted to search the vector and compare manually.

I found that this question had success using std::function::target with getting access to underlying pointers, but I can't use this, since I'm using std::bind to initialize the callback:

std::function<void(void *)> fnCallback = std::bind(&wdog::onBark, this, std::placeholders::_1)


I just want to compare the underlying member function ptrs, or even comparison with the underlying object ptr to which the member function is associated. Is there any way?

I'd like to avoid wrapping the member fn ptr in an object that contains a hash, although it looks like I might have to go that way...

Answer

When I do this, I return a token to the listening code.

My usual pattern is to have a weak_ptr<function<sig>> in the broadcaster, and the token is a shared_ptr<void> (to the stored weak ptr).

When broadcasting, I filter out dead targets, then broadcast. Targets deregister by simply clearing, destroying or otherwise discarding their token. A vector of tokens in their instance is a reasonable way if they want to never deregister.

If you never broadcast this can lead to old dead resources hanging around needlessly, so in a public framework I might want something with bettter guarantees. But it is lightweight easy and fast otherwise.