Jak dodać usuń std :: functions ze std :: vector [duplicate]

Sep 08 2020

Mam poniżej prosty program w C ++, który rejestruje niektóre wywołania zwrotne / nasłuchujące, które są po prostu std::functions. A następnie usuwa wywołania zwrotne.

Kod:

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

Pytanie:
Problem polega na tym, UnregisterListenerże nie kompiluje się i kończy się niepowodzeniem z następującym błędem.

error: overload resolution selected deleted operator '=='

Ale jest to dokładnie sposób używany do znajdowania i usuwania elementu z pliku std::vector. Prawda? Co ja robię źle?

Ogólnie rzecz biorąc, moje pytanie to również sprawdzenie, czy jest to właściwy sposób dodawania i usuwania słuchaczy w C ++ przy użyciu std::functions?

Przeglądając tę dyskusję , czy powinienem przechowywać rzeczywisty adres funkcji, a nie std:functions w std::vector?

Odpowiedzi

2 AsteroidsWithWings Sep 08 2020 at 17:45

Nie możesz porównywać std::functions ( z wyjątkiem znullptr ), więc to podejście nigdy nie zadziała ( findnie możesz zlokalizować funkcji, której szukasz).

Zamiast tego zawiń std::functionw jakąś klasę, która również ma unikalny identyfikator dla każdej z nich, a następnie porównaj go (używając niestandardowego komparatora dla find).

Alternatywnie, i jeśli nie przeszkadza trochę dynamicznej alokacji, można owinąć std::functions w std::shared_ptr<>i sklep / pass tych wokół porównania. Należy jednak pamiętać, że dwa różne (ale „identyczne”) funktory nadal porównywałyby w tym przypadku fałsz, więc musisz dokładnie przemyśleć, co próbujesz osiągnąć i jak należy użyć swojego kodu.

Tak czy inaczej, ListenerTypepowinno to być coś więcej niż tylko alias.