如何从 std::vector 添加删除 std::functions

How to add an remove std::functions from a std::vector

我有一个简单的 C++ 程序,它注册了一些 callbacks/listeners,它们只是 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, shared_from_this(), std::placeholders::_1));
    }

    void UnregisterAllListeners() {
        m_some_class.UnregisterListener(std::bind(&SomeOtherClass::ListenerMethod1, shared_from_this(), std::placeholders::_1));
        m_some_class.UnregisterListener(std::bind(&SomeOtherClass::ListenerMethod2, shared_from_this(), 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::functions 在 C++ 中添加和删除侦听器的正确方法?

查看 this discussion,我是否必须存储函数的实际地址而不是 std::vector 中的 std:function

您无法比较 std::functions (except with nullptr),因此该方法永远行不通(find 无法找到您要查找的函数)。

相反,将 std::function 包装到一些 class 中,每个 class 也有一个唯一的 ID,然后比较它(对 find 使用自定义比较器)。

或者,如果您不介意一点动态分配,您可以将 std::function 包装在 std::shared_ptr<> 中,然后将 store/pass 包装在周围进行比较。但是,请注意,在这种情况下,两个不同(但“相同”)的仿函数仍然会比较 false,因此您需要仔细考虑您要实现的目标以及需要如何使用您的代码。

无论如何,ListenerType 不应该只是一个别名。