boost lambda und set



  • Hallo Forum,

    Ich will eine std::set<ptr> nicht nach Speicheradressen, sondern nach Werten sortieren. Mein Ansatz sieht so aus, dass ich mit Boost.Lambda ein Funktionsobjekt erstelle, das den Inhalt der Zeiger vor dem Vergleich dereferenziert.
    Mein Ansatz dafür sieht so aus:

    #include <algorithm>
    #include <iostream>
    #include <memory>
    #include <set>
    #include <boost/lambda/lambda.hpp>
    using namespace std;
    using namespace boost::lambda;
    
    typedef tr1::shared_ptr< int > ptr;
    
    int main() {
        // std::set soll nach den Werten und nicht nach den Adressen sortiert werden
        // Fehlermeldung: error C2974: "std::set": Ungültiges template-Argument für "_Pr", Typ erwartet.
        set< ptr, (*_1 < *_2) > s;
    
        s.insert(ptr(new int (3)));
        s.insert(ptr(new int (6)));
        s.insert(ptr(new int (1)));
        s.insert(ptr(new int (4)));
        s.insert(ptr(new int (8)));
        s.insert(ptr(new int (7)));
        s.insert(ptr(new int (2)));
        s.insert(ptr(new int (5)));
    
        // erwünschte Ausgabe: 12345678
        for_each(s.begin(), s.end(), cout << *_1);
        cout << endl;
    }
    

    Sieht jemand den Fehler?
    Erzeugt (*_1 < *_2) etwa kein Funktionsobjekt?

    MFG



  • Das Problem hier ist, dass (*_1 < *_2) ein Ausdruck ist, welches ein Funktionsobjekt liefert. Es ist kein Typ. Hier kannst Du Boost-Lambdas generell nicht einsetzen, weil der Typ eines Boost-Lambda-objekts sehr umständlich aufzuschreiben ist.



  • funktioniert dass dann irgendwie mit Boost.Bind?
    Wie würdest du das denn machen?



  • daersc schrieb:

    funktioniert dass dann irgendwie mit Boost.Bind?
    Wie würdest du das denn machen?

    boost bind liefert ebenfalls einen ausdruck. du brauchst einen typen.
    Ich wuerde nen einfachen functor schreiben... und dann ein typedef oder template typedef auf das set machen:

    //functor
    struct deref_less_than {
      template<typename T>
      bool operator(T const& a, T const& b) {
        return *a < *b;
      }
    };
    
    //template typedef auf das set
    template<typename T>
    struct ptr_set {
      typedef std::set<T, deref_less_than> type;
    };
    
    //verwendung
    int main() {
        ptr_set<ptr>::type s;
    
        s.insert(ptr(new int (3)));
        s.insert(ptr(new int (6)));
        s.insert(ptr(new int (1)));
        s.insert(ptr(new int (4)));
        s.insert(ptr(new int (8)));
        s.insert(ptr(new int (7)));
        s.insert(ptr(new int (2)));
        s.insert(ptr(new int (5)));
    
        // erwünschte Ausgabe: 12345678
        for_each(s.begin(), s.end(), cout << *_1);
        cout << endl;
    }
    


  • Shade Of Mine schrieb:

    Ich wuerde nen einfachen functor schreiben... (...)

    //functor
    struct deref_less_than {
      template<typename T>
      bool operator(T const& a, T const& b) {
        return *a < *b;
      }
    };
    

    Gibt es da vielleicht schon was von Boost oder einer anderen LIB?



  • Wenn Du es unbedingt mit 'nem Boost-Funktor machen willst, kannst Du es über ein Funktionstemplate lösen:

    template<class Functor>
    void mein_hauptprogramm(Functor fun)
    {
      set<ptr,Functor> menge (fun);
      ...
    }
    
    int main()
    {
      mein_hauptprogramm( *_1<*_2 );
    }
    

    oder über C++0x-Erweiterungen:

    int main() {
      auto functor = *_1 < *_2;
      set<ptr,decltype(functor)> menge (functor);
      ...
    }
    

    Das erste wäre für mich allerdings keine Alternative.

    kk


Anmelden zum Antworten