我想编写一个最小的多播委托类。它的接口包含三个运算符 operator() 用于调用委托和 operator+=/operator-= 用于添加/删除可调用类型,如函数、方法、lambda 或仿函数。
我在实现 operator-= 时遇到了麻烦,我需要比较函数目标的地址以进行删除。到目前为止,这是我想出的(我使用 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;
};
当我用以下代码替换 TODO 行时,operator-= 适用于函数:
return * eventHandler.template target<void (*)(EventArgs...)>() ==
*_eventHandler.template target<void (*)(EventArgs...)>();
这是一个最小的例子:
void eventHandler() { /* ... */ }
Event<> event;
event += eventHandler;
event();
event -= eventHandler; // works
但是,对于其他可调用类型,它会崩溃,因为 std::function.target() 返回空指针。显然模板不再适合,所以我尝试模板 Event::operator-= 但由于“不完整类型”,它不能编译最可调用的类型:
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;
}
我也尝试过 T* 作为 target() 的模板参数,但我被卡住了。是否可以编写一个通用 operator-= 来正确比较任何可调用类型?
提前致谢!