问题描述
我有一个简单的C ++程序,下面注册了一些std::function
回调/监听器。然后删除回调。
代码:
#include <iostream>
#include <functional>
#include <vector>
#include <memory>
class SomeClass {
public:
typedef std::function<void(int)> ListenerType;
std::vector<ListenerType> m_listeners;
void RegisterListener(const ListenerType& listener) {
m_listeners.push_back(listener);
}
void UnregisterListener(const ListenerType& listener) {
// This does not compile. Is this the right way to remove an std::function from va ector of std::functions?
auto position= std::find(m_listeners.begin(),m_listeners.end(),listener);
if (position != m_listeners.end()) {
m_listeners.erase(position);
}
}
};
class SomeOtherClass : public std::enable_shared_from_this<SomeOtherClass>{
public:
SomeOtherClass(SomeClass some_class) : m_some_class(some_class) {
}
void RegisterAllListeners() {
m_some_class.RegisterListener(std::bind(&SomeOtherClass::ListenerMethod1,shared_from_this(),std::placeholders::_1));
m_some_class.RegisterListener(std::bind(&SomeOtherClass::ListenerMethod2,std::placeholders::_1));
}
void UnregisterAllListeners() {
m_some_class.UnregisterListener(std::bind(&SomeOtherClass::ListenerMethod1,std::placeholders::_1));
m_some_class.UnregisterListener(std::bind(&SomeOtherClass::ListenerMethod2,std::placeholders::_1));
}
private:
SomeClass m_some_class;
void ListenerMethod1(int value) {
std::cout << "The value is: " << value << std::endl;
}
void ListenerMethod2(int value) {
std::cout << "The value is: " << value << std::endl;
}
};
int main() {
SomeClass some_class;
SomeOtherClass some_other_class(some_class);
some_other_class.RegisterAllListeners();
some_other_class.UnregisterAllListeners();
}
问题:
问题是UnregisterListener
无法编译,并由于以下错误而失败。
error: overload resolution selected deleted operator '=='
但是,这正是从std::vector
中查找和删除项目的方式。是不是我在做什么错了?
总体来说,我的问题还在于检查这是否是使用std::function
s在C ++中添加和删除侦听器的正确方法?
翻阅this discussion,我是否必须在std:function
中存储函数的实际地址而不是存储std::vector
?
解决方法
您无法比较std::function
(except with nullptr
),因此这种方法永远行不通(find
无法找到您要查找的功能)。
相反,请将std::function
包装到每个也具有唯一ID的类中,然后进行比较(使用find
的自定义比较器)。
或者,如果您不介意进行动态分配,则可以将std::function
包装在std::shared_ptr<>
中,然后将它们存储/传递以进行比较。但是,请注意,在这种情况下,两个截然不同(但“相同”)的函子仍然会比较false,因此您需要仔细考虑要实现的目标以及如何使用代码。
无论哪种方式,ListenerType
都应不仅仅是别名。