I want to code a minimal multicast delegate class. Its interface consists of the three operators operator() for calling the delegate and operator+=/operator-= for adding/removing callable types like functions, methods, lambdas or functors.
I have trouble to implement operator-= where I need to compare addresses of function targets for removal. Here is what I came up with so far (I use g++ 4.6.3):
#include <functional>
#include <list>
template <typename ... EventArgs>
class Event
{
public:
typedef std::function<void (EventArgs...)> EventHandler;
Event() = default;
~Event() = default;
Event(const Event &) = delete;
Event & operator=(const Event &) = delete;
void operator()(EventArgs... eventArgs)
{
for (auto eventHandler : m_eventHandlers)
eventHandler(eventArgs...);
}
Event & operator+=(const EventHandler &eventHandler)
{
m_eventHandlers.push_back(eventHandler);
return *this;
}
Event & operator-=(const EventHandler &eventHandler)
{
m_eventHandlers.remove_if([&](const EventHandler &_eventHandler)
{
return false; // TODO: Compare event handlers
});
return *this;
}
private:
std::list<EventHandler> m_eventHandlers;
};
operator-= works for functions when I substitute the TODO line with the following code:
return * eventHandler.template target<void (*)(EventArgs...)>() ==
*_eventHandler.template target<void (*)(EventArgs...)>();
Here is a minimal example:
void eventHandler() { /* ... */ }
Event<> event;
event += eventHandler;
event();
event -= eventHandler; // works
However, for other callable types it crashes since std::function.target() returns null pointers. Obviously the template doesn’t fit anymore so I tried to template Event::operator-= but it does not compile for the most callable types due to “incomplete types”:
template<typename T>
Event & operator-=(const T &eventHandler)
{
m_eventHandlers.remove_if([&](const EventHandler &_eventHandler)
{
if (_eventHandler.template target<T>() != null_ptr) // <- ERROR
{
// ...
}
});
return *this;
}
I also tried T* as template parameter for target() but I’m stuck. Is it possible to code a generic operator-= that can correctly compare any callable type?
Thanks in advance!
The problem is that
std::function<>doesn’t support comparison operators==and!=.boost::functionhas an explanation for that.One solution is to store the functions in a map or a hash keyed by an integer. Registration would return that integer key. To unregister the key has to be passed, e.g.: