2012-12-27 17 views
7

Sind ForwardIterators als OutputIterators erforderlich? Meine aktuelle STL-Implementierung (VS2012) leitet forward_iterator_tag sowohl von input_iterator_tag als auch output_iterator_tag ab, aber ich kann diese Anforderung nicht im Standard [N3485] finden.Sind Forward-Iteratoren Output-Iteratoren?

Antwort

11

In C++ 11, Nein, Vorwärts-Iteratoren müssen nicht ausgegeben werden Iteratoren. Die Anforderungen des Ausgabe-Iterators sind wie eine zusätzliche Menge von Anforderungen, die ein Iterator haben kann, unabhängig von den übrigen Iteratoranforderungen, die er erfüllt. Vorwärts-Iteratoren sind nur Eingangs Iteratoren sein erforderlich (§24.2.5/1):

A-Klasse oder Zeigertyp X erfüllt die Anforderungen eines Vorwärts-Iterator, wenn:

  • X erfüllt die Anforderungen der ein InputIterator
  • ...

In der Tat, ein vorwärts-Iterator erfüllt die Output-Iterator Anforderungen nur, wenn es ein veränderliches Iterator zu einem Sequen ist Kopie der zuweisbaren Typen .

† oder ein konstanter Iterator für eine Sequenz von Typen mit operator=(...) const definiert mit veränderbaren Elementen.

Mehr zu dem Punkt, werden die Iterator-Tags speziell durch den Standard als (§24.4.3/2) definiert:

Wie Sie sehen können, forward_iterator_tag nur von input_iterator_tag erben sollte.


In C++ 03 wird darauf hingewiesen, dass zukunfts Iteratoren die Anforderungen der Eingangs- und Ausgangs Iteratoren erfüllen:

Vorwärts-Iteratoren erfüllen alle Anforderungen an die Eingangs- und Ausgangs Iteratoren und kann verwendet werden, wann immer eine Art angegeben ist.

Aber dies wird dann im folgenden Absatz widersprochen, die besagen, dass ein konstanter Vorwärts Iterator würde nicht die Anforderungen für die Ausgabe Iteratoren erfüllen:

Neben seiner Kategorie, einer nach vorn, bidirektionale oder Random-Access-Iterator kann auch veränderbar oder konstant sein, je nachdem, ob das Ergebnis des Ausdrucks * i sich als Referenz oder als Referenz auf eine Konstante verhält. Konstante Iteratoren erfüllen nicht die Anforderungen für Ausgabe-Iteratoren, und das Ergebnis des Ausdrucks * i (für konstanten Iterator i) kann nicht in einem Ausdruck verwendet werden, für den ein lvalue erforderlich ist.

Die Definition der Iterator-Tags ist jedoch identisch mit der in C++ 11. Es gab eine defect report für diese widersprüchliche Formulierung, aber es wurde als kein Fehler geschlossen, weil das erste Zitat im "einleitenden Text" des Abschnitts ist und würde wahrscheinlich in der Zukunft (was es war) umformuliert werden.


Die SGI definition of a forward iterator als Verfeinerung der beiden Eingangs- und Ausgangs Iteratoren (Dank in den Kommentaren @BenVoigt) gegeben.

Dennoch, wenn wir uns die implementation of the iterator tags ansehen, finden wir, dass forward_iterator_tag immer noch nur von input_iterator_tag erbt.

Sieht aus wie dies ein Bereich von ziemlich viel Verwirrung in der Vergangenheit gewesen ist, aber wenn VS2012 forward_iterator_tag als Erben von beiden output_ ist die Definition - und input_iterator_tag, kann ich nur annehmen, dass es ein Fehler ist.

+0

Aber beachten Sie, dass diese von der SGI-Definition, anders zu sein scheint, wo die Dokumentation sagt, dass ForwardIterator „eine Verfeinerung von InputIterator und OutputIterator“ ist, das heißt, es existiert ForwardInputIterator und ForwardOutputIterator aber nicht einfach ForwardIterator kann das Konzept nicht allein stehen. –

+0

@BenVoigt Es scheint, dass dies zwischen C++ 03 und C++ 11 geändert wurde. Edit: Warte, eigentlich ist es verwirrend. –

+0

@sftrabbit: Danke, dass du das geklärt hast. Was ist nun die kanonische Methode, einen Iterator sowohl als vorwärts als auch als Ausgabe zu kennzeichnen? (Führen Sie einfach ein neues privates Tag ein, das von beiden erbt, oder gibt es einen anderen Weg?) – MFH