Iterieren über variable container Typen



  • Dazu muss man decltype auf einen Ausdruck anwenden, nicht auf einen Typ wie im Beispiel von volkard. So wäre die richtige Lösung mit decltype :

    for (decltype(container.begin()) it = container.begin(); it != container.end(); ++it) {
    


  • Habe ein bischen rumprobiert und so klappt es auch bei mir hehe

    typedef decltype(container.begin()) myiterator;
    
        for(myiterator it = container.begin(); it != container.end(); it++){
            std::cout << *it << " ";
        }
    

    decltype scheint gerade bei template zeugs recht praktisch zu sein glaube ich. Es sieht für mich quasi so aus wie das Gegenstück zu auto, dass man dem Typ quasi wieder rausbekommt aus etwas.

    Danke euch!



  • akustiker schrieb:

    Hm, wenn ich das schreibe kommt "error: argument to decltype must be an expression".

    Ach, sorry, den typeof brauchte ich, damit ich ein foreach(-Makro) bauen konnte, dem man nur den containernamen reinstecken muss.

    for(typeof(cont.begin())=cont.begin()…
    

    Bei Dir reicht sebi707s Vorgehen.



  • Mal eine andere evtl. etwas blöse Frage:
    Wieso benutzen fast alle pre-increments in for-loop mit iteratoren (sprich ++it statt it++) ? Müsste so nicht das erste Element übersprungen werden, da beim ersten Durchlauf direkt inkrementiert wird?

    C++ newb checkin in... 😃



  • akustiker schrieb:

    Mal eine andere evtl. etwas blöse Frage:
    Wieso benutzen fast alle pre-increments in for-loop mit iteratoren (sprich ++it statt it++) ? Müsste so nicht das erste Element übersprungen werden, da beim ersten Durchlauf direkt inkrementiert wird?
    C++ newb checkin in... 😃

    Nee, der Unterschied ist NUR, wenn Du den Wert von ++i oder i++ sofort anschaust.

    int i=5;
    int j=++i;//j=6
    //i=6!!!
    
    int i=5;
    int j=i++;//j=5
    //i=6!!!
    

    Also sowas machen nur Verbrecher:

    if(++i==17)
    

    Warum nicht einfach

    ++i;
    if(i==17)
    

    Und beachte mal:

    i++;
    if(i==17)
    

    macht GENAU das gleiche!

    Deswegen isses egal, ob man ++i oder i++ schreibt, solange man den Wert davon nicht sofort verwendet. Und das machst Du doch nicht, denn Du bist kein Verbrecher, oder? Nach dem Semikolon am Anweisungsende (oder nem anderen sequence point) hat i den richtigen Wert und nur den kriegen die anderen zu sehen.

    Außerdem, vielleicht die andere Verwirrnis:

    for(init;conf;iter)
       cmd;
    

    ist

    {
       init;
       while(cond)
       {
          cmd;
          iter;
       }
    

    Beachte, daß das iter erst am Ende der Schleife steht, nach dem ersten Durchlauf erst.

    Also nix mit Überspringen. Keine Gefahr.

    Der Grund für ++i statt i++ ist, daß wenn das Erzeugen von Iteratoren teuer wäre (was es in der Praxis eigentlich nie ist), dann w+rde ++i schneller sein als i++, weil nur eine Referenz zurückgegeben werden muss statt einer ganzen Kopie des Iterators.



  • Üblicherweise übergibt man nicht den ganzen container, sondern nur den anfangs- und enditerator. So kann man auch präziser den Bereich auswählen, der bearbeitet werden soll.
    @akustiker: der letzte teil der for-schleife wird für sich nach jeden schleifendurchlauf abgearbeitet, sodass in beiden fällen der iterator nach jeden durchgang erhöht wird. Allerdings kann es sein, je nach implementatiom des iterators, dass die post-variante langsamer ist. Bei einem post-inkrement wird der iterator erhoht und der alte iterator zurückgegeben, welcher somit kopiert werden muss.



  • Ah alles klar, das macht Sinn.

    Danke 🙂



  • roflo schrieb:

    Üblicherweise übergibt man nicht den ganzen container, sondern nur den anfangs- und enditerator. So kann man auch präziser den Bereich auswählen, der bearbeitet werden soll.

    Was sich hoffentlich mit Ranges ändern wird, da ich es super nervig finde überall .begin() und .end() zu schreiben.



  • sebi707 schrieb:

    roflo schrieb:

    Üblicherweise übergibt man nicht den ganzen container, sondern nur den anfangs- und enditerator. So kann man auch präziser den Bereich auswählen, der bearbeitet werden soll.

    Was sich hoffentlich mit Ranges ändern wird, da ich es super nervig finde überall .begin() und .end() zu schreiben.

    +1 👍



  • volkard schrieb:

    akustiker schrieb:

    das aber mit meinem typename C irgendwie immer zu Compile Fehlern führt.

    Jo, also, typeof, _typeof_, decltype oder sowas brauchste eigentlich.

    for(_typeof_(C)::iterator i=container.begin(),e=container.end();i!=e;++e)
    

    Wieso inkrementierst du den end-of iterator? Typo?



  • sebi707 schrieb:

    roflo schrieb:

    Üblicherweise übergibt man nicht den ganzen container, sondern nur den anfangs- und enditerator. So kann man auch präziser den Bereich auswählen, der bearbeitet werden soll.

    Was sich hoffentlich mit Ranges ändern wird, da ich es super nervig finde überall .begin() und .end() zu schreiben.

    gibt es nicht sone range member function schon bei multimaps oder so? meine da irgendwas gelesen zu haben. Gibt dann nen pair mit first = begin() und second = end()



  • Sewing schrieb:

    Wieso inkrementierst du den end-of iterator? Typo?

    Jau.


Anmelden zum Antworten