Kann ich einen Reverse-Iterator in einen Forward-Iterator umwandeln?

Kann ich einen Reverse-Iterator in einen Forward-Iterator umwandeln?

Reverse-Iteratoren haben ein Member base() die einen entsprechenden Forward-Iterator zurückgibt. Beachten Sie, dass dies nicht ist ein Iterator, der auf dasselbe Objekt verweist – er verweist tatsächlich auf das nächste Objekt in der Sequenz. Das ist so, dass rbegin() entspricht end() und rend() entspricht begin() .

Wenn Sie also einen Iterator zurückgeben möchten, würden Sie so etwas tun wie

std::deque<Move>::const_iterator Current() const
{
    if (forward)
        return currentfwd;
    else
        return (currentbck+1).base();
}

Ich würde es jedoch vorziehen, eine Referenz zurückzugeben und alle Iterationsdetails innerhalb der Klasse zu kapseln.


Das ist genau die Art von Problem, die das Design von STL veranlasste, damit zu beginnen. Es gibt echte Gründe für:

  1. Iteratoren nicht zusammen mit Containern speichern
  2. Verwenden von Algorithmen, die beliebige Iteratoren akzeptieren
  3. Wenn Algorithmen ein ganzes Sortiment statt eines einzelnen Artikels auf einmal auswerten lassen

Ich vermute, was Sie gerade sehen, ist mehr oder weniger die Spitze des Eisbergs der wirklichen Probleme. Mein Rat wäre, einen Schritt zurückzutreten und anstatt zu fragen, wie man mit den Details des Designs in seiner jetzigen Form umgeht, eine etwas allgemeinere Frage darüber zu stellen, was Sie zu erreichen versuchen und wie Sie dies am besten erreichen Endergebnis.

Für diejenigen, denen die Titelfrage in erster Linie am Herzen liegt, ist die Antwort ein stark eingeschränktes „Ja“. Insbesondere hat ein reverse_iterator einen base() Mitglied dazu. Etwas problematisch sind allerdings die Qualifikationen.

Um das Problem zu demonstrieren, betrachten Sie Code wie diesen:

#include <iostream>
#include <vector>
#include <iterator>

int main() { 
    int i[] = { 1, 2, 3, 4};
    std::vector<int> numbers(i, i+4);

    std::cout << *numbers.rbegin() << "\n";
    std::cout << *numbers.rbegin().base() << "\n";
    std::cout << *(numbers.rbegin()+1).base() << "\n";

    std::cout << *numbers.rend() << "\n";
    std::cout << *numbers.rend().base() << "\n";
    std::cout << *(numbers.rend()+1).base() << "\n";
}

Wenn Sie dies zu diesem bestimmten Zeitpunkt auf meinem speziellen Computer ausführen, wird die folgende Ausgabe erzeugt:

4
0
4
-1879048016
1
-1879048016

Zusammenfassung:mit rbegin() wir müssen Fügen Sie einen hinzu, bevor Sie ihn in einen Forward-Iterator umwandeln, um einen gültigen Iterator zu erhalten – aber mit rend() wir dürfen nicht Fügen Sie vor der Konvertierung einen hinzu, um einen gültigen Iterator zu erhalten.

Solange Sie X.rbegin() verwenden und X.rend() als Parameter für einen generischen Algorithmus ist das in Ordnung -- aber die Erfahrung zeigt, dass die Umwandlung in Forward-Iteratoren oft zu Problemen führt.

Am Ende ist die Antwort für den Hauptteil der Frage (im Gegensatz zum Titel) jedoch ziemlich genau wie oben angegeben:Das Problem ergibt sich aus dem Versuch, ein Objekt zu erstellen, das die Sammlung mit ein paar Iteratoren in dieser Sammlung kombiniert . Beheben Sie dieses Problem, und das ganze Geschäft mit Forward- und Reverse-Iteratoren wird hinfällig.


Seit std::deque ist ein Container mit wahlfreiem Zugriff (dasselbe wie std::vector ) sind Sie viel besser dran, einen einzelnen Ganzzahlindex in der Deque für beide Durchläufe zu verwenden.