eigenen iterator



  • hallo, hab eine klasse und möchte ihn um einen eigenen Iterator erweitern.
    Im <bits/iterator> Header hab ich auch eine generische Version gefunden.

    Leider kann ich ihn nicht verweenden wie ich möchte da er keine funktionen implementiert. Gibt es einen Fertigen oder muss ich selbst einen implementieren?

    So dachte ich, würde es funktionieren

    <iterator>
    
    class myclass
    {
      class MyClassData{};
      MyClassData Data[N];
    public:
      typedef std::iterator<std::random_access_iterator_tag,MyClassData> iterator;
      typedef std::iterator<std::random_access_iterator_tag,MyClassData const> const_iterator;
    
      iterator begin()
      {
        return iterator( this->Data[0] );
      };
    //...
    
    };
    

    Danke im vorraus



  • Was ist bits? Das gehört nicht zum Standard, soweit ich weiß. Wenn der Header jedenfalls da ist und keine Implementierung davon, kannst du ihn auch nicht nutzen. Aber vielleicht benötigst Du auch einfach nur eine entsprechende lib dazu. Übrigens implementiert er durchaus die begin-Funktion zumindest. Was fehlt Dir denn?

    Edits: Freundlicher.



  • <bits/iterator> wird von <iterator> inkludiert, welche zur std gehört.

    "ihn" : da hab ich mich verschrieben, meinte da die klasse (also einfach mit "die klasse" ersetzen)



  • Warum nimmst du für deinen Iterator nicht einfach einen Pointer?



  • Eisflamme schrieb:

    Übrigens implementiert er durchaus die begin-Funktion zumindest. Was fehlt Dir denn?
    Edits:

    dem iterator fehlen alle operatoren ++,*, != , etc



  • ipsec schrieb:

    Warum nimmst du für deinen Iterator nicht einfach einen Pointer?

    Mein Beispiel ist etwas vereinfacht...
    Gegenfrage: wieso benutzt der std::vector keinen pointer sondern einen Iterator?



  • Ich sag ja nur, dass mein MSVC keinen bits-Ordner kennt und daher auch schlecht inkludieren kann. Wenn ich <bits/iterator> inkludieren will, kriege ich auch einen Fehler. Und da die Implementierung bei dir fehlt, gehe ich außerdem davon aus, dass der iterator nicht dafür gedacht ist, das zu tun, was du möchtest. Was heißt überhaupt generische Version, findest du in dieser Datei eine abstrakte Basisklasse?



  • <bits/...> hat in Deinem Code nichts zu suchen. Ob der Header nun von irgendeinem anderen Standardheader eingebunden wird oder nicht. Er ist ein "Implementierungsdetail", auf das Du Dich nicht verlassen kannst. Das heißt, in der nächsten GCC Version könnte das Ding verschwinden. Und mit dem C++ Compiler von Microsoft wirst Du Dein Programm auch nicht übersetzen können, weil es höchstwahrscheinlich keine <bits/...>-Header dort gibt.

    Um zu Vermeiden, dass Du Dich auf weitere Implementierungsdetails versehentlich verlässt, solltest Du Dir entsprechendes Lehrmaterial zu C++ und der Standardbibliothek besorgen. Da steht dann auch drin, was einen Iterator ausmacht.

    In Deinem Fall wäre ein "normaler" Zeiger nutzbar.

    Ob std::vector auch normale Zeiger oder etwas anderes verwendet, wird nicht festgelegt. Das ist wieder ein Implementierungsdetail, was Dich nicht zu interessieren hat. Du kannst aber davon ausgehen, dass, auch wenn es kein Zeiger sein sollte, der Iterator zumindest genauso performant sein sollte (zumindest bei eingeschalteter Compiler-Optimierung und ohne libstdc++-Debugmodus).



  • krümelkacker schrieb:

    In Deinem Fall wäre ein "normaler" Zeiger nutzbar.

    In meinem gezeigten Fall ja. Oder ich könnte den Iterator vom std::vector nutzen:

    std::vector<MyClassData>::iterator
    

    Ich möchte aber noch weitere anbieten, die eine andere "Sicht" auf die Daten hergeben.
    Dazu könnte man annehmen das MyClass eine Baumstruktur darstellst und ich möchte verschiedene Darstellungen Iteratormässig implementieren, damit ich es gut mit den stl-Algorithmen kombinieren kann.

    krümelkacker schrieb:

    <bits/...> hat in Deinem Code nichts zu suchen. Ob der Header nun von irgendeinem anderen Standardheader eingebunden wird oder nicht. Er ist ein "Implementierungsdetail", auf das Du Dich nicht verlassen kannst. Das heißt, in der nächsten GCC Version könnte das Ding verschwinden. Und mit dem C++ Compiler von Microsoft wirst Du Dein Programm auch nicht übersetzen können, weil es höchstwahrscheinlich keine <bits/...>-Header dort gibt.

    Das weis ich, hab nach std::iterator gesuchen und meine suche hat mich dorthin gefürt...Ich wollte damit nur andeuten, dass die exsistenz des iterators mich glauben lässt es gebe irgendwo einen fertigen iterator welcher zb auch von std::vector genutzt wird.

    Ich würde gern wissen wie ich eigene Iteratoren implementieren kann?
    Muss ich alles selber machen oder gibts da schon vordefinierte die ich nutzen könnte ?



  • Es gibt Hilfsmittel (Boost.Iterator), welche das Erzeugen eigener Iteratoren erleichtern. Was für eine Datenstruktor willst Du Dir denn bauen, dass Du eigene Iteratoren brauchst? Vielleicht geht es ja auch ohne...



  • Hab einige Datenstrukturen z.B:

    class Baum
    {
      Baum* Parent;
      std::vector<Baum*> Nodes;
    };
    

    Da bräuchte ich z.B:
    - Parent-Iterator : Iteriert sich durch die Parents
    - Node-Iterator : trivial
    - Descent-Iterator : iteriert sich durch alle Nodes - Anschliesend die Nodes der Nodes usw...
    - etc...



  • ja dann ... Bost.Iterator kann Dir helfen.

    Beispiel:

    class node
    {
      node* parent;
      vector<node*> children;
      typedef vector<node*>::const_iterator vpbcit;
    public:
      typedef boost::indirect_iterator<vpbcit,const node> const_children_iterator;
      typedef boost::indirect_iterator<vpbcit,      node>       children_iterator;
    
      children_iterator children_begin()
        { return children_iterator(children.begin()); }
      children_iterator children_end()
        { return children_iterator(children.end()); }
      ...
    };
    

    Ob Dein Vorhaben sinnvoll ist, kann ich im Moment nicht beurteilen.



  • rion schrieb:

    Hab einige Datenstrukturen z.B:

    class Baum
    {
      Baum* Parent;
      std::vector<Baum*> Nodes;
    };
    

    Da bräuchte ich z.B:
    - Parent-Iterator : Iteriert sich durch die Parents
    - Node-Iterator : trivial
    - Descent-Iterator : iteriert sich durch alle Nodes - Anschliesend die Nodes der Nodes usw...
    - etc...

    Du suchst also Iteratoren um die verschiedenen Traversierungsarten durch Bäume abbilden zu können? Wieso machst Du das nicht mit rekursiven Funktionen? Und wenn die Performance wirklich eine Rolle spielt, solltest Du den Baum sowieso nicht hierarchisch sondern in einem vector ablegen.



  • Diese Iteratoren-Dinge gehören zu <iterator> und ja, sie sind dazu da, eigene Iteratoren zu bauen. Allerdings musst du von ihnen Ableiten.

    Ich habe das bei meiner Implementierung der std::list folgendermaßen gemacht:

    template <typename T>
    class List<T>::iterator : public std::iterator<std::bidirectional_iterator_tag, T>
    {
        ListNode* pos;
        friend class List<T>;
    
        explicit iterator(ListNode* p) : pos(p) {}
    
    public:
        iterator& operator ++ ()    { pos = pos->next; return *this; }
        iterator  operator ++ (int) { iterator iter(pos); pos = pos->next; return iter; }
    
        iterator& operator -- ()    { pos = pos->prev; return *this; }
        iterator  operator -- (int) { iterator iter(pos); pos = pos->prev; return iter; }
    
        reference operator *  () { return pos->value; }
        pointer   operator -> () { return &pos->value; }
    
        bool operator == (const iterator& iter) const { return pos == iter.pos; }
        bool operator != (const iterator& iter) const { return pos != iter.pos; }
    };
    

    Für const_iterator ist alles gleich, außer ein paar const's mehr.



  • Danke PI, genau das was ich wissen wollte!


Log in to reply