eigenen Iterator implementieren



  • Hallo,

    ich habe aus einer Abfrage von einer C-Library eine Elementliste verpackt in einem mit anderen Dingen enthaltenen Struct bekommen. Für diese C-Lib und Struktur habe ich bisher eine Facade gebaut, die das mit weiteren zusammenhängenden Infos kapselt.

    Jetzt würde ich auf dieser Facade gern einen eigenen Iterator implementieren. Ich habe schon Boost.Iterators gefunden, habe aber bisher die Dokumentation nicht wirklich verstanden.

    Also ich würde gern auf der Facaden Klasse ein begin(), end() ++operator, *operator aufrufen aber bin unsicher was da alles zugehört. Kennt jemand ein einfaches Beispiel wir man zu einer derartigen Klasse eine Iteratorfunktion hinzufügt?

    Danke! 😕



  • class mein_iterator : public boost::iterator_facade<mein_iterator, ???>
    {
    public:
      ??? dereference() const { return ???; }
      bool equal(mein_iterator const& j) const { return ???; }
      void increment() { ??? }
      void decrement() { ??? }
      void advance(???) { ??? }
      ??? distance_to(mein_iterator const& j) const { return ???; }
    private:
      ???
    };
    

  • Mod

    Es schadet eventuell nicht, wenigstens einmal einen Iterator vollständig selber zu implementieren. Dann sieht man, dass es dabei zu Codewiederholung im großen Stil kommt und versteht, was für Arbeit einem durch Boost wie und warum abgenommen werden. Dann wird auch klar, warum die iterator_facade gerade die Funktionen haben möchte, die es möchte und wie diese aussehen müssen.



  • Hallo GmbH,

    Da Du nichts über die Elementliste oder die Facade gesagt hast, lässt sich die Frage so pauschal nicht beantworten. Mal angenommen, Du hast eine Struktur wie diese hier:

    struct S
    {
        double weissnich;
        int data[200];
        int anzahl; // Anzahl der belegten Elemente in 'data[]'
    };
    

    Dann ist es am einfachsten, mit einem boost.iterator_adaptor anzufangen.

    #include <boost/iterator/iterator_adaptor.hpp>
    #include <cassert>
    //                                                              +-------------- Basistyp "ein Iterator"
    //                                                              |           +-- Value Type des Iterators
    //                                                              |           |
    class S_iterator : public boost::iterator_adaptor< S_iterator, int*, /*const*/ int, boost::forward_traversal_tag >
    {
    public:
        explicit S_iterator( int* p )
            : iterator_adaptor_( p )
        {}
    };
    
    S_iterator begin( S& s )
    {
        return S_iterator( s.data );
    }
    S_iterator end( S& s )
    {
        assert( s.anzahl >= 0 );
        assert( s.anzahl <= sizeof(s.data)/sizeof(*s.data) );
        return S_iterator( s.data + s.anzahl );
    }
    

    inklusive der beiden Funktionen begin und end , die Dir Iteratoren auf den Anfang und das Ende des Containers liefern.

    So sind Aufrufe wie

    S s;
        // s belegen ...
        copy( begin(s), end(s), ostream_iterator< int >( cout, " " ) ); // Elemente ausgeben
        cout << endl;
        S_iterator i = find( begin(s), end(s), 101 ); // suche 101 im Container
    

    .. sofort möglich.

    Wenn Du für den Valuetype const int statt int wählst, so erhältst Du einen const_iterator - d.h. Du kannst über diesen Iterator die Elemente nicht verändern.
    Den Traversal-Tag kann man hier auch gegen boost::bidirectional_traversal_tag bzw. boost::random_access_traversal_tag austauschen. Du solltest aber nur das auswählen, was Du wirklich brauchst, um ggf. versehentlichen Missbrauch zu unterbinden.

    Solltest Du kein Array sondern eine verkettete Struktur als Ausgangssituation haben, so ist hier beschrieben, wie dann vorzugehen ist. Aber auch das geschieht mit dem iterator_adaptor . iterator_facade benötigt man eigentlich nie, solange darunter nur irgendwas containerartiges vorliegt.
    Unter dem angegebenen Link ist auch beschrieben, wie man mit einem Klassentemplate einen iterator und den dazugehörigen const_iterator erzeugt. Inklusive der Konvertierung von iterator nach const_iterator.

    Gruß
    Werner


Anmelden zum Antworten