Cómo agregar una función remove std :: de un std :: vector [duplicate]

Sep 08 2020

Tengo un programa C ++ simple a continuación que registra algunas devoluciones de llamada / oyentes que son solo std::functions. Y luego elimina las devoluciones de llamada.

Código:

#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();
}

Pregunta:
El problema es que UnregisterListenerno se compila y falla con el siguiente error.

error: overload resolution selected deleted operator '=='

Pero, esta es exactamente la forma que se utiliza para buscar y eliminar un elemento de un std::vector. ¿No es así? ¿Qué estoy haciendo mal?

En general, mi pregunta también es verificar si esta es la forma correcta de agregar y eliminar oyentes en C ++ usando std::functions?

Mirando esta discusión , ¿debería tener que almacenar la dirección real de la función en lugar de la std:functions en el std::vector?

Respuestas

2 AsteroidsWithWings Sep 08 2020 at 17:45

No puede comparar std::functions ( excepto connullptr ), por lo que ese enfoque nunca funcionará ( findno puede ubicar la función que está buscando).

En su lugar, envuelva el std::functionen alguna clase que también tenga un ID único para cada uno, luego compárelo (usando un comparador personalizado para find).

Alternativamente, y si no le importa un poco de asignación dinámica, puede envolver los correos std::functionelectrónicos std::shared_ptr<>y almacenarlos / pasarlos para compararlos. Sin embargo, tenga en cuenta que dos functores distintos (pero "idénticos") seguirían comparando false en este caso, por lo que debe pensar cuidadosamente sobre lo que está tratando de lograr y cómo debe usarse su código.

De cualquier manera, ListenerTypedebería ser algo más que un alias.