假设有以下类:
#include <functional>
#include <vector>
template<typename T1> class Signaler
{
public:
typedef std::function<void (T1)> Func;
public:
Signaler()
{
}
void Call(T1 arg)
{
for(Int32 i = (Int32)_handlers.size() - 1; i > -1; i--)
{
Func handler = _handlers[i];
handler(arg);
}
}
Signaler& operator+=(Func f)
{
_handlers.push_back( f );
return *this;
}
Signaler& operator-=(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
{
if ( (*i).template target<void (T1)>() == f.template target<void (T1)>() )
{
_handlers.erase( i );
break;
}
}
return *this;
}
private:
std::vector<Func> _handlers;
};我使用它的方式如下:
信号器Global::Signal_SelectionChanged;
class C1
{
public:
void Register()
{
Global::Signal_SelectionChanged += [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void Unregister()
{
Global::Signal_SelectionChanged -= [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {}
};
class C2
{
public:
void Register()
{
Global::Signal_SelectionChanged += [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void Unregister()
{
Global::Signal_SelectionChanged -= [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {}
};现在,我遇到的问题是,当我从类C2中调用'Unregister‘时,它删除了'lambda’表达式的错误版本,因为‘lambda’看起来很相似。
我该如何解决这个问题?
有什么想法吗?
谢谢
发布于 2014-01-24 18:25:15
问题是您使用的std::function::target的类型不是存储在std::function中的对象的类型,所以它返回一个空指针。也就是说,您需要知道存储在std::function中的对象的实际类型才能调用target。
即使您使用用于添加回调的lambda闭包类型调用target,这也不会起作用,原因有两个:首先,lambda闭包类型是唯一的(5.1.2p3),因此+=和-= lambda具有不同的类型,即使它们在语法上相同;其次,lambda表达式的闭包类型没有定义为具有operator== (5.1.2p3-6,19-20),因此您的代码甚至无法编译。
从lambda切换到std::bind不会有什么帮助,因为绑定类型也没有定义为具有operator==。
相反,可以考虑使用id来注册/注销回调。您也可以使用自己的函数器来定义operator==,但这将是一项大量的工作。
https://stackoverflow.com/questions/21328229
复制相似问题