【发布时间】:2012-05-16 08:07:46
【问题描述】:
我想编写一个最小的多播委托类。它的接口由三个用于调用委托的运算符 operator() 和用于添加/删除可调用类型(如函数、方法、lambda 或仿函数)的 operator+=/operator-= 组成。
我在实现 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-= 来正确比较任何可调用类型?
提前致谢!
【问题讨论】:
-
既然您评论说您保证目标具有可比性,您可能希望使用自己的类型擦除解决方案(这需要基础类型,即
std::functionlingo 中的目标)来建模例如 EqualityComparable)。
标签: c++ lambda c++11 function-pointers std-function