2011-01-03 11 views
11

Say chcesz zapisać następujące:wektora std :: funkcji <>

typedef std::function<void(int)> MyFunctionDecl; 

..w kolekcji:

typedef std::vector<MyFunctionDecl> FunctionVector; 
FunctionVector v; 

Jest to możliwe, ale jeśli chcę znaleźć coś za pomocą std::find:

FunctionVector::const_iterator cit = std::find(v.begin(), v.end(), myFunctionDecl); 

.. my się błąd ze względu na operatora ==.

Jak sugerowano mi w poprzednim pytaniu dotyczącym tego, to można zdobyć wokół przez umieszczenie deklaracji funkcji wewnątrz innej klasy, który zapewnia == operatora:

class Wrapper 
{ 
private: 
    MyFunctionDecl m_Func; 

public: 
    // ctor omitted for brevity 

    bool operator == (const Wrapper& _rhs) 
    { 
     // are they equal? 
    }; // eo == 
}; // eo class Wrapper 

Więc co chcę zrobić w jakiś sposób generuje skrót dla "MyFunctionDecl", dzięki czemu mogę poprawnie zaimplementować operatora ==. Mógłbym mieć jakiś unikalny identyfikator i poprosić rozmówcę o podanie unikalnego identyfikatora dla delegata, ale wydaje się to być trochę uciążliwe i podatne na błędy.

Czy istnieje sposób, że mogę to zrobić? Aby te same funkcje zwracały ten sam identyfikator do celów porównawczych? Do tej pory jedynym sposobem na to jest zrzucenie pojęcia o użyciu std::function i powrót do korzystania z szybkich delegatów, które obsługują porównania. Ale potem tracę zdolność używania lambdas.

Każda pomoc doceniona!

EDIT

Biorąc pod uwagę poniżej odpowiedź, to co mam wymyślić ... żadnych zastrzeżeń mógłbym przegapić? Jestem w procesie wprowadzenie go poprzez jego kroków teraz:

class MORSE_API Event : boost::noncopyable 
{ 
public: 
    typedef std::function<void(const EventArgs&)> DelegateType; 
    typedef boost::shared_ptr<DelegateType> DelegateDecl; 

private: 
    typedef std::set<DelegateDecl> DelegateSet; 
    typedef DelegateSet::const_iterator DelegateSet_cit; 
    DelegateSet m_Delegates; 

public: 
    Event() 
    { 
    }; // eo ctor 


    Event(Event&& _rhs) : m_Delegates(std::move(_rhs.m_Delegates)) 
    { 
    }; // eo mtor 

    ~Event() 
    { 
    }; // eo dtor 

    // methods 
    void invoke(const EventArgs& _args) 
    { 
     std::for_each(m_Delegates.begin(), 
         m_Delegates.end(), 
         [&_args](const DelegateDecl& _decl) { (*_decl)(_args); }); 
    }; // eo invoke 

    DelegateDecl addListener(DelegateType f) 
    { 
     DelegateDecl ret(new DelegateType(f)); 
     m_Delegates.insert(ret); 
     return ret; 
    }; // eo addListener 

    void removeListener(const DelegateDecl _decl) 
    { 
     DelegateSet_cit cit(m_Delegates.find(_decl)); 
     if(cit != m_Delegates.end()) 
      m_Delegates.erase(cit); 
    }; // eo removeListener 

}; // eo class Event 
+1

Dlaczego musisz znaleźć?Jeśli potrzebujesz znaleźć taką funkcję std ::, musisz ją znaleźć na podstawie jakiegoś identyfikatora lub podobnego, powiedzmy automatycznie wygenerowanego int dla każdego tworzonego Wrappera. Znajdź int dla przyszłego porównania i upewnij się, że tworzysz tylko jedno opakowanie. – villintehaspam

+0

Nie można porównywać funkcji, jest to * problem z zatrzymaniem * (http://en.wikipedia.org/wiki/Halting_problem) –

+2

@Alexandre Myślę, że problem zatrzymania jest powiązany, ale zdecydowanie nie jest taki sam. Myślę, że pomysł hasha jest taki, że nie trzeba uruchamiać tej funkcji, aby ją porównać. –

Odpowiedz

6

Pan spojrzał na Boost Signals? Może już robić to, co chcesz robić.

W każdym razie, prostym sposobem zawijania function byłoby użycie shared_ptr. Jeśli nie

typedef std::shared_ptr<std::function<void(int)> > MyFunctionDecl; 

i upewnij się, że funkcja jest owinięta bezpośrednio wewnątrz shared_ptr podczas jego tworzenia (tak, że wskaźnik jest niepowtarzalny), wskaźniki mogą być testowane pod kątem równości tak std::find będzie działać.

Na przykład można to zrobić za pomocą funkcji fabrycznego jak

template <class Functor> 
MyFunctionDecl createDelegate(Functor f) { 
    return MyFunctionDecl(new std::function<void(int)>(f)); 
} 

ten sposób można dać niepowtarzalną tożsamość do jej funkcji (wskaźnik) podczas tworzenia delegata.

BTW, ja używać std::set zamiast std::vector, zarówno jako find i erase są logarytmiczny zamiast liniowego.

+0

dzięki za to. Stworzyłem wdrożenie, biorąc pod uwagę twój pomysł i jestem w trakcie sprawdzania go teraz. Zmieniono mój pierwotny post, aby pokazać aktualny kod. Dzięki! –

-1
#include <boost/type_traits.hpp> 
#include <iostream> 

template<typename T> 
class Wrapper 
{ 
    private: 
     T m_Func; 

    public: 

     template<typename U> 
     bool operator==(const Wrapper<U>& _rhs) 
     { 
      return boost::is_same<T, U>::value; 
     } 
}; 

int main() 
{ 
    Wrapper<int> Wint; 
    Wrapper<bool> Wbool; 
    std::cout << (Wint == Wbool) << std::endl; 
    std::cout << (Wint == Wint) << std::endl; 
} 
+0

To naprawdę nie rozwiązuje problemu. boost :: is_same sprawdza równość typu, a nie równość obiektu. – villintehaspam

+1

Ale Wrapper ma operatora == –

+0

Tak, więc rób wiele innych zajęć, które nie pomagają ani ... :) – villintehaspam

Powiązane problemy