From cppreference.com
template<classI>conceptrandom_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(Ii,constIj,conststd::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>>;};(since C++20)The concept random_access_iterator refines
by adding support for constant time advancement with the +=, +, -=, and - operators, constant time computation of distance with -, and array notation with subscripting [].
Iterator concept determination
Definition of this concept is specified via an exposition-only alias template /*ITER_CONCEPT*/.
In order to determine /*ITER_CONCEPT*/<I>, let ITER_TRAITS<I> denote I if the specialization std::iterator_traits<I> is generated from the primary template, or std::iterator_traits<I> otherwise:
If ITER_TRAITS<I>::iterator_concept is valid and names a type, /*ITER_CONCEPT*/<I> denotes the type.
Otherwise, if ITER_TRAITS<I>::iterator_category is valid and names a type, /*ITER_CONCEPT*/<I> denotes the type.
Otherwise, if std::iterator_traits<I> is generated from the primary template, /*ITER_CONCEPT*/<I> denotes
std::random_access_iterator_tag
.
(That is, std::derived_from</*ITER_CONCEPT*/<I>,std::random_access_iterator_tag> is assumed to be true.)
Otherwise, /*ITER_CONCEPT*/<I> does not denote a type and results in a substitution failure.
Semantic requirements
Let a and b be valid iterators of type I such that b is reachable from a, and let n be a value of type std::iter_difference_t<I> equal to b-a. std::random_access_iterator<I> is modeled only if all the concepts it subsumes are modeled and:
(a+=n) is equal to b.
std::addressof(a+=n) is equal to std::addressof(a).
(a+n) is equal to (a+=n).
(a+n) is equal to (n+a).
For any two positive integers x and y, if a+(x+y) is valid, then a+(x+y) is equal to (a+x)+y.
a+0 is equal to a.
If (a+(n-1)) is valid, then --b is equal to (a+(n-1)).
(b+=-n) and (b-=n) are both equal to a.
std::addressof(b-=n) is equal to std::addressof(b).
(b-n) is equal to (b-=n).
If b is dereferenceable, then a[n] is valid and is equal to *b.
bool(a<=b) is true.
Every required operation has constant time complexity.
Note that
returns the address of the iterator object, not the address of the object the iterator points to. I.e. operator+= and operator-= must return a reference to *this.
Equality preservation
Expressions declared in
of the standard library concepts are required to be
(except where stated otherwise).
Implicit expression variations
A
that uses an expression that is non-modifying for some constant lvalue operand also requires
implicit expression variations
.
Notes
Unlike the
requirements, the random_access_iterator concept does not require dereference to return an lvalue.
Example
Demonstrates a possible implementation of
via C++20 concepts.
Run this code
#include<iterator>namespacecxx20{template<std::input_or_output_iteratorIter>constexprstd::iter_difference_t<Iter>distance(Iterfirst,Iterlast){ifconstexpr(std::random_access_iterator<Iter>)returnlast-first;else{std::iter_difference_t<Iter>result{};for(;first!=last;++first)++result;returnresult;}}}intmain(){staticconstexprautoil={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);}See also