Namensräume
Varianten
Aktionen

std::random_access_iterator

Von cppreference.com
< cpp‎ | iterator
 
 
Iterator-Bibliothek
Iterator-Konzepte
random_access_iterator
(C++20)


Iterator-Primitive
Algorithmus-Konzepte und Hilfsprogramme
Indirekte aufrufbare Konzepte
Gemeinsame Algorithmus-Anforderungen
(C++20)
(C++20)
(C++20)
Dienstprogramme
(C++20)
Iterator-Adapter
Bereichszugriff
(C++11)(C++14)
(C++14)(C++14)  
(C++11)(C++14)
(C++14)(C++14)  
(C++17)(C++20)
(C++17)
(C++17)
 
Definiert in Header <iterator>
template< class I >

    concept random_access_iterator =
        std::bidirectional_iterator<I> &&
        std::derived_from</*ITER_CONCEPT*/<I>, std::random_access_iterator_tag> &&
        std::totally_ordered<I> &&
        std::sized_sentinel_for<I, I> &&
        requires(I i, const I j, const std::iter_difference_t<I> n) {
            { i += n } -> std::same_as<I&>;
            { j +  n } -> std::same_as<I>;
            { n +  j } -> std::same_as<I>;
            { i -= n } -> std::same_as<I&>;
            { j -  n } -> std::same_as<I>;
            {  j[n]  } -> std::same_as<std::iter_reference_t<I>>;

        };
(seit C++20)

Das Konzept random_access_iterator verfeinert bidirectional_iterator durch Hinzufügen der Unterstützung für konstante Zeitfortschritte mit den Operatoren +=, +, -= und -, konstante Zeitberechnung der Distanz mit - und Array-Notation mit der Subskriptierung [].

Inhalt

[bearbeiten] Bestimmung des Iterator-Konzepts

Die Definition dieses Konzepts wird über ein expositions-only-Alias-Template /*ITER_CONCEPT*/ spezifiziert.

Um /*ITER_CONCEPT*/<I> zu bestimmen, bezeichne ITER_TRAITS<I> I, wenn die Spezialisierung std::iterator_traits<I> aus der Primärvorlage generiert wird, oder std::iterator_traits<I> andernfalls.

  • Wenn ITER_TRAITS<I>::iterator_concept gültig ist und einen Typ benennt, bezeichnet /*ITER_CONCEPT*/<I> diesen Typ.
  • Andernfalls, wenn ITER_TRAITS<I>::iterator_category gültig ist und einen Typ benennt, bezeichnet /*ITER_CONCEPT*/<I> diesen Typ.
  • Andernfalls, wenn std::iterator_traits<I> aus der primären Vorlage generiert wird, bezeichnet /*ITER_CONCEPT*/<I> std::random_access_iterator_tag.
  • Andernfalls bezeichnet /*ITER_CONCEPT*/<I> keinen Typ und führt zu einem Substitutionsfehler.

[edit] Semantische Anforderungen

Seien a und b gültige Iteratoren des Typs I, so dass b von a erreichbar ist, und sei n ein Wert vom Typ std::iter_difference_t<I> gleich b - a. std::random_access_iterator<I> wird nur dann modelliert, wenn alle von ihm umfassten Konzepte modelliert werden und

  • (a += n) gleich b ist.
  • std::addressof(a += n) ist gleich std::addressof(a). [1]
  • (a + n) ist gleich (a += n).
  • (a + n) ist gleich (n + a).
  • Für zwei positive ganze Zahlen x und y gilt: Wenn a + (x + y) gültig ist, dann ist a + (x + y) gleich (a + x) + y.
  • a + 0 ist gleich a.
  • Wenn (a + (n - 1)) gültig ist, dann ist --b gleich (a + (n - 1)).
  • (b += -n) und (b -= n) sind beide gleich a.
  • std::addressof(b -= n) ist gleich std::addressof(b). [1]
  • (b - n) ist gleich (b -= n).
  • Wenn b dereferenzierbar ist, dann ist a[n] gültig und gleich *b.
  • bool(a <= b) ist true.
  • Jede erforderliche Operation hat konstante Zeitkomplexität.

Beachten Sie, dass std::addressof die Adresse des Iterator-Objekts zurückgibt, nicht die Adresse des Objekts, auf das der Iterator zeigt. D. h. operator+= und operator-= müssen eine Referenz auf *this zurückgeben.

[bearbeiten] Gleichheitserhaltung

Ausdrücke, die in requires-Ausdrücken der Standardbibliothekskonzepte deklariert sind, müssen gleichheitserhaltend sein (sofern nicht anders angegeben).

[bearbeiten] Implizite Ausdrucksvariationen

Ein requires-Ausdruck, der einen Ausdruck verwendet, der für einen konstanten Lvalue-Operanden nicht-modifizierend ist, erfordert ebenfalls implizite Ausdrucksvariationen.

[edit] Anmerkungen

Im Gegensatz zu den LegacyRandomAccessIterator-Anforderungen erfordert das Konzept random_access_iterator nicht, dass die Dereferenzierung ein lvalue zurückgibt.

[edit] Beispiel

Demonstriert eine mögliche Implementierung von std::distance mittels C++20-Konzepten.

#include <iterator>
 
namespace cxx20
{
    template<std::input_or_output_iterator Iter>
    constexpr std::iter_difference_t<Iter> distance(Iter first, Iter last)
    {
        if constexpr(std::random_access_iterator<Iter>)
            return last - first;
        else
        {
            std::iter_difference_t<Iter> result{};
            for (; first != last; ++first)
                ++result;
            return result;
        }
    }
}
 
int main()
{
    static constexpr auto il = {3, 1, 4};
 
    static_assert(std::random_access_iterator<decltype(il.begin())> &&
                  cxx20::distance(il.begin(), il.end()) == 3 &&
                  cxx20::distance(il.end(), il.begin()) == -3);
}

[edit] Siehe auch

spezifiziert, dass ein forward_iterator ein bidirektionaler Iterator ist, der die Rückwärtsbewegung unterstützt
(Konzept) [bearbeiten]
gibt an, dass ein random_access_iterator ein zusammenhängender Iterator ist, der sich auf Elemente bezieht, die im Speicher zusammenhängend sind
(Konzept) [bearbeiten]