[iterators] (original) (raw)

23.1 General [iterators.general]

The following subclauses describe iterator requirements, and components for iterator primitives, predefined iterators, and stream iterators, as summarized in Table 82.

23.3 Iterator requirements [iterator.requirements]

23.3.1 In general [iterator.requirements.general]

Iterators are a generalization of pointers that allow a C++ program to work with different data structures (for example, containers and ranges) in a uniform manner.

To be able to construct template algorithms that work correctly and efficiently on different types of data structures, the library formalizes not just the interfaces but also the semantics and complexity assumptions of iterators.

An input iteratorisupports the expression*i, resulting in a value of some object typeT, called thevalue typeof the iterator.

An output iterator i has a non-empty set of types that areindirectly_­writable to the iterator; for each such type T, the expression *i = ois valid where o is a value of type T.

For every iterator typeX, there is a corresponding signed integer-like type ([iterator.concept.winc]) called thedifference typeof the iterator.

Since iterators are an abstraction of pointers, their semantics are a generalization of most of the semantics of pointers in C++.

This ensures that every function template that takes iterators works as well with regular pointers.

This document defines six categories of iterators, according to the operations defined on them:input iterators,output iterators,forward iterators,bidirectional iterators,random access iterators, andcontiguous iterators, as shown in Table 83.

Table 83: Relations among iterator categories [tab:iterators.relations]

🔗 Contiguous Random Access Bidirectional Forward Input
🔗 Output

The generic term iterator refers to any type that models theinput_­or_­output_­iterator concept ([iterator.concept.iterator]).

Forward iterators meet all the requirements of input iterators and can be used whenever an input iterator is specified; Bidirectional iterators also meet all the requirements of forward iterators and can be used whenever a forward iterator is specified; Random access iterators also meet all the requirements of bidirectional iterators and can be used whenever a bidirectional iterator is specified; Contiguous iterators also meet all the requirements of random access iterators and can be used whenever a random access iterator is specified.

Iterators that further meet the requirements of output iterators are called mutable iterators.

Nonmutable iterators are referred to as constant iterators.

In addition to the requirements in this subclause, the nested typedef-names specified in [iterator.traits]shall be provided for the iterator type.

[Note 1:

Either the iterator type must provide the typedef-names directly (in which case iterator_­traits pick them up automatically), or an iterator_­traits specialization must provide them.

— _end note_]

Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence.

Such a value is called a past-the-end value.

Values of an iterator ifor which the expression *i is defined are called dereferenceable.

The library never assumes that past-the-end values are dereferenceable.

Iterators can also have singular values that are not associated with any sequence.

Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that meet the_Cpp17DefaultConstructible_ requirements, using a value-initialized iterator as the source of a copy or move operation.

[Note 2:

This guarantee is not offered for default-initialization, although the distinction only matters for types with trivial default constructors such as pointers or aggregates holding pointers.

— _end note_]

In these cases the singular value is overwritten the same way as any other value.

Dereferenceable values are always non-singular.

Most of the library's algorithmic templates that operate on data structures have interfaces that use ranges.

A range is an iterator and a sentinelthat designate the beginning and end of the computation, or an iterator and a count that designate the beginning and the number of elements to which the computation is to be applied.234

An iterator and a sentinel denoting a range are comparable.

A range [i, s) is empty if i == s; otherwise, [i, s) refers to the elements in the data structure starting with the element pointed to byiand up to but not including the element, if any, pointed to by the first iterator j such that j == s.

A sentinel s is called reachable from an iterator i if and only if there is a finite sequence of applications of the expression++i that makes i == s.

If s is reachable from i, [i, s) denotes a valid range.

A counted range is empty if n == 0; otherwise, refers to the n elements in the data structure starting with the element pointed to by i and up to but not including the element, if any, pointed to by the result of n applications of ++i.

A counted range is valid if and only if n == 0; or n is positive, i is dereferenceable, and is valid.

The result of the application of library functions to invalid ranges is undefined.

All the categories of iterators require only those functions that are realizable for a given category in constant time (amortized).

Therefore, requirement tables and concept definitions for the iterators do not specify complexity.

Destruction of a non-forward iterator may invalidate pointers and references previously obtained from that iterator.

An invalid iteratoris an iterator that may be singular.235

Iterators are called constexpr iteratorsif all operations provided to meet iterator category requirements are constexpr functions.

[Note 3:

For example, the types “pointer to int” andreverse_­iterator<int*> are constexpr iterators.

— _end note_]

23.3.2 Associated types [iterator.assoc.types]

23.3.2.1 Incrementable traits [incrementable.traits]

To implement algorithms only in terms of incrementable types, it is often necessary to determine the difference type that corresponds to a particular incrementable type.

Accordingly, it is required that if WI is the name of a type that models theweakly_­incrementable concept ([iterator.concept.winc]), the typeiter_difference_t<WI> be defined as the incrementable type's difference type.

namespace std { template<class> struct incrementable_traits { };template<class T> requires is_object_v<T> struct incrementable_traits<T*> { using difference_type = ptrdiff_t;};template<class I> struct incrementable_traits<const I> : incrementable_traits<I> { };template<class T> requires requires { typename T::difference_type; } struct incrementable_traits<T> { using difference_type = typename T::difference_type;};template<class T> requires (!requires { typename T::difference_type; } && requires(const T& a, const T& b) { { a - b } -> integral; }) struct incrementable_traits<T> { using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>;};template<class T> using iter_difference_t = see below;}

Let be remove_­cvref_­t<I>.

The type iter_­difference_­t<I> denotes

Users may specialize incrementable_­traits on program-defined types.

23.3.2.2 Indirectly readable traits [readable.traits]

To implement algorithms only in terms of indirectly readable types, it is often necessary to determine the value type that corresponds to a particular indirectly readable type.

Accordingly, it is required that if R is the name of a type that models the indirectly_­readable concept ([iterator.concept.readable]), the typeiter_value_t<R> be defined as the indirectly readable type's value type.

template<class> struct cond-value-type { }; template<class T> requires is_object_v<T> struct cond-value-type<T> { using value_type = remove_cv_t<T>;};template<class> struct indirectly_readable_traits { };template<class T> struct indirectly_readable_traits<T*> : cond-value-type<T> { };template<class I> requires is_array_v<I> struct indirectly_readable_traits<I> { using value_type = remove_cv_t<remove_extent_t<I>>;};template<class I> struct indirectly_readable_traits<const I> : indirectly_readable_traits<I> { };template<class T> requires requires { typename T::value_type; } struct indirectly_readable_traits<T> : cond-value-type<typename T::value_type> { };template<class T> requires requires { typename T::element_type; } struct indirectly_readable_traits<T> : cond-value-type<typename T::element_type> { };template<class T> using iter_value_t = see below;

Let be remove_­cvref_­t<I>.

The type iter_­value_­t<I> denotes

Class template indirectly_­readable_­traits may be specialized on program-defined types.

[Note 1:

Some legacy output iterators define a nested type named value_­typethat is an alias for void.

These types are not indirectly_­readableand have no associated value types.

— _end note_]

[Note 2:

Smart pointers like shared_­ptr<int> are indirectly_­readable and have an associated value type, but a smart pointer like shared_­ptr<void>is not indirectly_­readable and has no associated value type.

— _end note_]

23.3.2.3 Iterator traits [iterator.traits]

To implement algorithms only in terms of iterators, it is sometimes necessary to determine the iterator category that corresponds to a particular iterator type.

Accordingly, it is required that ifIis the type of an iterator, the typeiterator_traits<I>::iterator_categorybe defined as the iterator's iterator category.

In addition, the typesiterator_traits<I>::pointer iterator_traits<I>::referenceshall be defined as the iterator's pointer and reference types; that is, for an iterator object a of class type, the same type asdecltype(a.operator->()) anddecltype(*a), respectively.

The typeiterator_­traits<I>​::​pointershall be voidfor an iterator of class type Ithat does not support operator->.

Additionally, in the case of an output iterator, the typesiterator_traits<I>::value_type iterator_traits<I>::difference_type iterator_traits<I>::referencemay be defined as void.

The definitions in this subclause make use of the following exposition-only concepts:template<class I> concept cpp17-iterator = copyable<I> && requires(I i) { { *i } -> can-reference;{ ++i } -> same_­as<I&>;{ *i++ } -> can-reference;};template<class I> concept cpp17-input-iterator = cpp17-iterator<I> && equality_­comparable<I> && requires(I i) { typename incrementable_traits<I>::difference_type;typename indirectly_readable_traits<I>::value_type;typename common_reference_t<iter_reference_t<I>&&,typename indirectly_readable_traits<I>::value_type&>;typename common_reference_t<decltype(*i++)&&,typename indirectly_readable_traits<I>::value_type&>;requires signed_integral<typename incrementable_traits<I>::difference_type>;};template<class I> concept cpp17-forward-iterator = cpp17-input-iterator<I> && constructible_­from<I> && is_lvalue_reference_v<iter_reference_t<I>> && same_­as<remove_cvref_t<iter_reference_t<I>>,typename indirectly_readable_traits<I>::value_type> && requires(I i) { { i++ } -> convertible_­to<const I&>;{ *i++ } -> same_­as<iter_reference_t<I>>;};template<class I> concept cpp17-bidirectional-iterator = cpp17-forward-iterator<I> && requires(I i) { { --i } -> same_­as<I&>;{ i-- } -> convertible_­to<const I&>;{ *i-- } -> same_­as<iter_reference_t<I>>;};template<class I> concept cpp17-random-access-iterator = cpp17-bidirectional-iterator<I> && totally_­ordered<I> && requires(I i, typename incrementable_traits<I>::difference_type n) { { i += n } -> same_­as<I&>;{ i -= n } -> same_­as<I&>;{ i + n } -> same_­as<I>;{ n + i } -> same_­as<I>;{ i - n } -> same_­as<I>;{ i - i } -> same_­as<decltype(n)>;{ i[n] } -> convertible_­to<iter_reference_t<I>>;};

The members of a specialization iterator_­traits<I> generated from theiterator_­traits primary template are computed as follows:

Explicit or partial specializations of iterator_­traits may have a member type iterator_­concept that is used to indicate conformance to the iterator concepts ([iterator.concepts]).

iterator_­traits is specialized for pointers asnamespace std { template<class T> requires is_object_v<T> struct iterator_traits<T*> { using iterator_concept = contiguous_iterator_tag;using iterator_category = random_access_iterator_tag;using value_type = remove_cv_t<T>;using difference_type = ptrdiff_t;using pointer = T*;using reference = T&;};}

[Example 1:

To implement a genericreversefunction, a C++ program can do the following:template<class BI> void reverse(BI first, BI last) { typename iterator_traits<BI>::difference_type n = distance(first, last);--n;while(n > 0) { typename iterator_traits<BI>::value_type tmp = *first;*first++ = *--last;*last = tmp; n -= 2;} }

— _end example_]

23.3.3 Customization point objects [iterator.cust]

23.3.3.1 ranges​::​iter_­move [iterator.cust.move]

The expression ranges​::​iter_­move(E) for a subexpression E is expression-equivalent to:

If ranges​::​iter_­move(E) is not equal to *E, the program is ill-formed, no diagnostic required.

23.3.3.2 ranges​::​iter_­swap [iterator.cust.swap]

Let iter-exchange-move be the exposition-only function:

template<class X, class Y> constexpr iter_value_t<X> _iter-exchange-move_(X&& x, Y&& y) noexcept(noexcept(iter_value_t<X>(iter_move(x))) && noexcept(*x = iter_move(y)));

Effects: Equivalent to:iter_value_t<X> old_value(iter_move(x));*x = iter_move(y);return old_value;

The expression ranges​::​iter_­swap(E1, E2) for subexpressionsE1 and E2 is expression-equivalent to:

23.3.4 Iterator concepts [iterator.concepts]

23.3.4.1 General [iterator.concepts.general]

For a type I, let ITER_­TRAITS(I) denote the type I if iterator_­traits<I> names a specialization generated from the primary template.

Otherwise, ITER_­TRAITS(I) denotesiterator_­traits<I>.

[Note 1:

ITER_­TRAITS enables independent syntactic determination of an iterator's category and concept.

— _end note_]

[Example 1:

struct I { using value_type = int;using difference_type = int;int operator*() const; I& operator++(); I operator++(int); I& operator--(); I operator--(int);bool operator==(I) const;}; iterator_­traits<I>​::​iterator_­category denotes input_­iterator_­tag, and ITER_­CONCEPT(I) denotes random_­access_­iterator_­tag.

— _end example_]

23.3.4.2 Concept indirectly_­readable [iterator.concept.readable]

Types that are indirectly readable by applying operator*model the indirectly_­readable concept, including pointers, smart pointers, and iterators.

template<class In> concept indirectly-readable-impl = requires(const In in) { typename iter_value_t<In>;typename iter_reference_t<In>;typename iter_rvalue_reference_t<In>;{ *in } -> same_as<iter_reference_t<In>>;{ ranges::iter_move(in) } -> same_as<iter_rvalue_reference_t<In>>;} && common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&> && common_reference_with<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&&> && common_reference_with<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>;

template<class In> concept indirectly_­readable = indirectly-readable-impl<remove_cvref_t<In>>;

Given a value i of type I, I models indirectly_­readableonly if the expression *i is equality-preserving.

[Note 1:

The expression *i is indirectly required to be valid via the exposition-only dereferenceable concept ([iterator.synopsis]).

— _end note_]

23.3.4.3 Concept indirectly_­writable [iterator.concept.writable]

The indirectly_­writable concept specifies the requirements for writing a value into an iterator's referenced object.

template<class Out, class T> concept indirectly_­writable = requires(Out&& o, T&& t) { *o = std::forward<T>(t); *std::forward<Out>(o) = std::forward<T>(t); const_cast<const iter_reference_t<Out>&&>(*o) = std::forward<T>(t); const_cast<const iter_reference_t<Out>&&>(*std::forward<Out>(o)) = std::forward<T>(t); };

Let E be an expression such that decltype((E)) is T, and let o be a dereferenceable object of type Out.

Out and T model indirectly_­writable<Out, T> only if

After evaluating any above assignment expression, o is not required to be dereferenceable.

[Note 1:

The only valid use of an operator* is on the left side of the assignment statement.

Assignment through the same value of the indirectly writable type happens only once.

— _end note_]

[Note 2:

indirectly_­writable has the awkward const_­cast expressions to reject iterators with prvalue non-proxy reference types that permit rvalue assignment but do not also permit const rvalue assignment.

Consequently, an iterator type I that returns std​::​stringby value does not model indirectly_­writable<I, std​::​string>.

— _end note_]

23.3.4.4 Concept weakly_­incrementable [iterator.concept.winc]

The weakly_­incrementable concept specifies the requirements on types that can be incremented with the pre- and post-increment operators.

The increment operations are not required to be equality-preserving, nor is the type required to be equality_­comparable.

template<class T> inline constexpr bool is-integer-like = see below; template<class T> inline constexpr bool is-signed-integer-like = see below; template<class I> concept weakly_­incrementable = default_initializable<I> && movable<I> && requires(I i) { typename iter_difference_t<I>;requires is-signed-integer-like<iter_difference_t<I>>;{ ++i } -> same_­as<I&>; i++; };

A type I is an integer-class typeif it is in a set of implementation-defined class types that behave as integer types do, as defined in below.

The range of representable values of an integer-class type is the continuous set of values over which it is defined.

The values 0 and 1 are part of the range of every integer-class type.

If any negative numbers are part of the range, the type is a signed-integer-class type; otherwise, it is an unsigned-integer-class type.

For every integer-class type I, let B(I) be a hypothetical extended integer type of the same signedness with the smallest width ([basic.fundamental]) capable of representing the same range of values.

The width of I is equal to the width of B(I).

Let a and b be objects of integer-class type I, let x and y be objects of type B(I) as described above that represent the same values as a and b respectively, and let c be an lvalue of any integral type.

Expressions of integer-class type are explicitly convertible to any integral type.

Expressions of integral type are both implicitly and explicitly convertible to any integer-class type.

Conversions between integral and integer-class types do not exit via an exception.

An expression E of integer-class type I is contextually convertible to boolas if by bool(E != I(0)).

A value-initialized object of integer-class type has value 0.

For every (possibly cv-qualified) integer-class type I,numeric_­limits<I> is specialized such that:

A type I is integer-likeif it models integral<I> or if it is an integer-class type.

A type I is signed-integer-likeif it models signed_­integral<I> or if it is a signed-integer-class type.

A type I is unsigned-integer-likeif it models unsigned_­integral<I> or if it is an unsigned-integer-class type.

is-integer-like<I> is trueif and only if I is an integer-like type.

is-signed-integer-like<I> is trueif and only if I is a signed-integer-like type.

Let i be an object of type I.

When i is in the domain of both pre- and post-increment, i is said to be incrementable.

I models weakly_­incrementable<I> only if

Recommended practice: The implementaton of an algorithm on a weakly incrementable type should never attempt to pass through the same incrementable value twice; such an algorithm should be a single-pass algorithm.

[Note 1:

For weakly_­incrementable types, a equals b does not imply that ++aequals ++b.

(Equality does not guarantee the substitution property or referential transparency.)

Such algorithms can be used with istreams as the source of the input data through the istream_­iterator class template.

— _end note_]

23.3.4.5 Concept incrementable [iterator.concept.inc]

The incrementable concept specifies requirements on types that can be incremented with the pre- and post-increment operators.

The increment operations are required to be equality-preserving, and the type is required to be equality_­comparable.

[Note 1:

This supersedes the annotations on the increment expressions in the definition of weakly_­incrementable.

— _end note_]

template<class I> concept incrementable = regular<I> && weakly_­incrementable<I> && requires(I i) { { i++ } -> same_­as<I>;};

Let a and b be incrementable objects of type I.

I models incrementable only if

[Note 2:

The requirement thata equals bimplies++a equals ++b(which is not true for weakly incrementable types) allows the use of multi-pass one-directional algorithms with types that model incrementable.

— _end note_]

23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]

The input_­or_­output_­iterator concept forms the basis of the iterator concept taxonomy; every iterator models input_­or_­output_­iterator.

This concept specifies operations for dereferencing and incrementing an iterator.

Most algorithms will require additional operations to compare iterators with sentinels ([iterator.concept.sentinel]), to read ([iterator.concept.input]) or write ([iterator.concept.output]) values, or to provide a richer set of iterator movements ([iterator.concept.forward],[iterator.concept.bidir], [iterator.concept.random.access]).

template<class I> concept input_­or_­output_­iterator = requires(I i) { { *i } -> can-reference;} && weakly_­incrementable<I>;

[Note 1:

Unlike the Cpp17Iterator requirements, the input_­or_­output_­iterator concept does not require copyability.

— _end note_]

23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]

The sentinel_­for concept specifies the relationship between an input_­or_­output_­iterator type and a semiregular type whose values denote a range.

Let s and i be values of type S andI such that [i, s) denotes a range.

TypesS and I model sentinel_­for<S, I> only if

The domain of == is not static.

Given an iterator i and sentinel s such that [i, s) denotes a range and i != s, i and s are not required to continue to denote a range after incrementing any other iterator equal to i.

Consequently, i == s is no longer required to be well-defined.

23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]

The sized_­sentinel_­for concept specifies requirements on an input_­or_­output_­iterator type I and a corresponding sentinel_­for<I>that allow the use of the - operator to compute the distance between them in constant time.

template<class S, class I> concept [sized_­sentinel_­for](#concept:sized%5Fsentinel%5Ffor "23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") = [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I> && !disable_sized_sentinel_for<remove_cv_t<S>, remove_cv_t<I>> && requires(const I& i, const S& s) { { s - i } -> [same_­as](concept.same#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<iter_difference_t<I>>;{ i - s } -> [same_­as](concept.same#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<iter_difference_t<I>>;};

Let i be an iterator of type I, and sa sentinel of type S such that [i, s) denotes a range.

Let N be the smallest number of applications of ++inecessary to make bool(i == s) be true.

S and I model sized_­sentinel_­for<S, I> only if

template<class S, class I> inline constexpr bool disable_sized_sentinel_for = false;

Remarks: Pursuant to [namespace.std], users may specialize disable_­sized_­sentinel_­forfor cv-unqualified non-array object types S and Iif S and/or I is a program-defined type.

Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.

[Note 1:

disable_­sized_­sentinel_­for allows use of sentinels and iterators with the library that satisfy but do not in fact model sized_­sentinel_­for.

— _end note_]

[Example 1:

The sized_­sentinel_­for concept is modeled by pairs ofrandom_­access_­iterators ([iterator.concept.random.access]) and by counted iterators and their sentinels ([counted.iterator]).

— _end example_]

23.3.4.9 Concept input_­iterator [iterator.concept.input]

The input_­iterator concept defines requirements for a type whose referenced values can be read (from the requirement forindirectly_­readable ([iterator.concept.readable])) and which can be both pre- and post-incremented.

[Note 1:

Unlike the Cpp17InputIterator requirements ([input.iterators]), the input_­iterator concept does not need equality comparison since iterators are typically compared to sentinels.

— _end note_]

template<class I> concept input_­iterator = input_­or_­output_­iterator<I> && indirectly_­readable<I> && requires { typename ITER_CONCEPT(I); } && derived_­from<_ITER_CONCEPT_(I), input_iterator_tag>;

23.3.4.10 Concept output_­iterator [iterator.concept.output]

The output_­iterator concept defines requirements for a type that can be used to write values (from the requirement forindirectly_­writable ([iterator.concept.writable])) and which can be both pre- and post-incremented.

template<class I, class T> concept output_­iterator = input_­or_­output_­iterator<I> && indirectly_­writable<I, T> && requires(I i, T&& t) { *i++ = std::forward<T>(t); };

Let E be an expression such that decltype((E)) is T, and let i be a dereferenceable object of type I.

I and T model output_­iterator<I, T> only if*i++ = E; has effects equivalent to:*i = E;++i;

Recommended practice: The implementation of an algorithm on output iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single-pass algorithm.

23.3.4.11 Concept forward_­iterator [iterator.concept.forward]

The forward_­iterator concept adds copyability, equality comparison, and the multi-pass guarantee, specified below.

template<class I> concept forward_­iterator = input_­iterator<I> && derived_­from<_ITER_CONCEPT_(I), forward_iterator_tag> && incrementable<I> && sentinel_­for<I, I>;

The domain of == for forward iterators is that of iterators over the same underlying sequence.

However, value-initialized iterators of the same type may be compared and shall compare equal to other value-initialized iterators of the same type.

[Note 1:

Value-initialized iterators behave as if they refer past the end of the same empty sequence.

— _end note_]

Pointers and references obtained from a forward iterator into a range [i, s) shall remain valid while [i, s) continues to denote a range.

Two dereferenceable iterators a and b of type Xoffer the multi-pass guarantee if:

[Note 2:

The requirement thata == bimplies++a == ++band the removal of the restrictions on the number of assignments through a mutable iterator (which applies to output iterators) allow the use of multi-pass one-directional algorithms with forward iterators.

— _end note_]

23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]

The bidirectional_­iterator concept adds the ability to move an iterator backward as well as forward.

template<class I> concept bidirectional_­iterator = forward_­iterator<I> && derived_­from<_ITER_CONCEPT_(I), bidirectional_iterator_tag> && requires(I i) { { --i } -> same_­as<I&>;{ i-- } -> same_­as<I>;};

A bidirectional iterator r is decrementable if and only if there exists some q such that++q == r.

Decrementable iterators r shall be in the domain of the expressions--r and r--.

Let a and b be equal objects of type I.

I models bidirectional_­iterator only if:

23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]

The random_­access_­iterator concept adds support for constant-time advancement with +=, +, -=, and -, as well as the computation of distance in constant time with -.

Random access iterators also support array notation via subscripting.

template<class I> concept random_­access_­iterator = bidirectional_­iterator<I> && derived_­from<_ITER_CONCEPT_(I), random_access_iterator_tag> && totally_­ordered<I> && sized_­sentinel_­for<I, I> && requires(I i, const I j, const iter_difference_t<I> n) { { i += n } -> same_­as<I&>;{ j + n } -> same_­as<I>;{ n + j } -> same_­as<I>;{ i -= n } -> same_­as<I&>;{ j - n } -> same_­as<I>;{ j[n] } -> same_­as<iter_reference_t<I>>;};

Let a and b be valid iterators of type Isuch that b is reachable from aafter n applications of ++a, let D be iter_­difference_­t<I>, and let n denote a value of type D.

I models random_­access_­iterator only if

23.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]

The contiguous_­iterator concept provides a guarantee that the denoted elements are stored contiguously in memory.

template<class I> concept contiguous_­iterator = random_­access_­iterator<I> && derived_­from<_ITER_CONCEPT_(I), contiguous_iterator_tag> && is_lvalue_reference_v<iter_reference_t<I>> && same_­as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> && requires(const I& i) { { to_address(i) } -> same_­as<add_pointer_t<iter_reference_t<I>>>;};

Let a and b be dereferenceable iterators andc be a non-dereferenceable iterator of type Isuch that b is reachable from a andc is reachable from b, and let D be iter_­difference_­t<I>.

The type I models contiguous_­iterator only if

23.3.5 C++17 iterator requirements [iterator.cpp17]

23.3.5.1 General [iterator.cpp17.general]

In the following sections,aandbdenote values of typeX or const X,difference_­type and reference refer to the types iterator_­traits<X>​::​difference_­type anditerator_­traits<X>​::​reference, respectively,ndenotes a value ofdifference_­type,u,tmp, andmdenote identifiers,rdenotes a value ofX&,tdenotes a value of value typeT,odenotes a value of some type that is writable to the output iterator.

[Note 1:

For an iterator type X there must be an instantiation of iterator_­traits<X> ([iterator.traits]).

— _end note_]

23.3.5.2 Cpp17Iterator [iterator.iterators]

The Cpp17Iterator requirements form the basis of the iterator taxonomy; every iterator meets the Cpp17Iterator requirements.

This set of requirements specifies operations for dereferencing and incrementing an iterator.

Most algorithms will require additional operations to read ([input.iterators]) or write ([output.iterators]) values, or to provide a richer set of iterator movements ([forward.iterators],[bidirectional.iterators], [random.access.iterators]).

A type X meets the Cpp17Iterator requirements if:

Table 84: Cpp17Iterator requirements [tab:iterator]

🔗 Expression Return type Operational Assertion/note
🔗 semantics pre-/post-condition
🔗 *r unspecified Preconditions: r is dereferenceable.
🔗 ++r X&

23.3.5.3 Input iterators [input.iterators]

A class or pointer typeXmeets the requirements of an input iterator for the value typeTifX meets the Cpp17Iterator ([iterator.iterators]) and_Cpp17EqualityComparable_ (Table 25) requirements and the expressions in Table 85 are valid and have the indicated semantics.

In Table 85, the termthe domain of ==is used in the ordinary mathematical sense to denote the set of values over which== is (required to be) defined.

This set can change over time.

Each algorithm places additional requirements on the domain of== for the iterator values it uses.

These requirements can be inferred from the uses that algorithm makes of == and !=.

[Example 1:

The call find(a,b,x)is defined only if the value of ahas the property _p_defined as follows:b has property _p_and a value ihas property p_if (*i==x) or if (*i!=xand++ihas property_p).

— _end example_]

Table 85: Cpp17InputIterator requirements (in addition to Cpp17Iterator) [tab:inputiterator]

🔗 Expression Return type Operational Assertion/note
🔗 semantics pre-/post-condition
🔗 a != b contextually convertible to bool !(a == b) Preconditions: (a, b) is in the domain of ==.
🔗 *a reference, convertible to T Preconditions: a is dereferenceable. The expression(void)*a, *a is equivalent to *a. If a == b and (a, b) is in the domain of == then *a is equivalent to *b.
🔗 a->m (*a).m Preconditions: a is dereferenceable.
🔗 ++r X& Preconditions: r is dereferenceable. Postconditions: r is dereferenceable or r is past-the-end;any copies of the previous value of r are no longer required to be dereferenceable nor to be in the domain of ==.
🔗 (void)r++ equivalent to (void)++r
🔗 *r++ convertible to T { T tmp = *r;++r;return tmp; }

Recommended practice: The implementation of an algorithm on input iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single pass algorithm.

[Note 1:

For input iterators, a == b does not imply ++a == ++b.

(Equality does not guarantee the substitution property or referential transparency.)

Value type T is not required to be a Cpp17CopyAssignable type (Table 31).

Such an algorithm can be used with istreams as the source of the input data through theistream_­iteratorclass template.

— _end note_]

23.3.5.4 Output iterators [output.iterators]

A class or pointer typeXmeets the requirements of an output iterator if X meets the Cpp17Iterator requirements ([iterator.iterators]) and the expressions in Table 86are valid and have the indicated semantics.

Table 86: Cpp17OutputIterator requirements (in addition to Cpp17Iterator) [tab:outputiterator]

🔗 Expression Return type Operational Assertion/note
🔗 semantics pre-/post-condition
🔗 *r = o result is not used Remarks: After this operation r is not required to be dereferenceable. Postconditions: r is incrementable.
🔗 ++r X& addressof(r) == addressof(++r). Remarks: After this operation r is not required to be dereferenceable. Postconditions: r is incrementable.
🔗 r++ convertible to const X& { X tmp = r; ++r; return tmp; } Remarks: After this operation r is not required to be dereferenceable. Postconditions: r is incrementable.
🔗 *r++ = o result is not used Remarks: After this operation r is not required to be dereferenceable. Postconditions: r is incrementable.

Recommended practice: The implementation of an algorithm on output iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single-pass algorithm.

[Note 1:

The only valid use of an operator*is on the left side of the assignment statement.

Assignment through the same value of the iterator happens only once.

Equality and inequality might not be defined.

— _end note_]

23.3.5.5 Forward iterators [forward.iterators]

A class or pointer typeXmeets the requirements of a forward iterator if

The domain of == for forward iterators is that of iterators over the same underlying sequence.

However, value-initialized iterators may be compared and shall compare equal to other value-initialized iterators of the same type.

[Note 1:

Value-initialized iterators behave as if they refer past the end of the same empty sequence.

— _end note_]

Two dereferenceable iterators a and b of type X offer themulti-pass guarantee if:

[Note 2:

The requirement thata == bimplies++a == ++b(which is not true for input and output iterators) and the removal of the restrictions on the number of the assignments through a mutable iterator (which applies to output iterators) allows the use of multi-pass one-directional algorithms with forward iterators.

— _end note_]

Table 87: Cpp17ForwardIterator requirements (in addition to Cpp17InputIterator) [tab:forwarditerator]

🔗 Expression Return type Operational Assertion/note
🔗 semantics pre-/post-condition
🔗 r++ convertible to const X& { X tmp = r; ++r; return tmp; }
🔗 *r++ reference

If a and b are equal, then either a and bare both dereferenceable or else neither is dereferenceable.

If a and b are both dereferenceable, then a == bif and only if*a and *b are bound to the same object.

23.3.5.6 Bidirectional iterators [bidirectional.iterators]

A class or pointer typeXmeets the requirements of a bidirectional iterator if, in addition to meeting the Cpp17ForwardIterator requirements, the following expressions are valid as shown in Table 88.

Table 88: Cpp17BidirectionalIterator requirements (in addition to Cpp17ForwardIterator) [tab:bidirectionaliterator]

🔗 Expression Return type Operational Assertion/note
🔗 semantics pre-/post-condition
🔗 --r X& Preconditions: there exists s such that r == ++s. Postconditions: r is dereferenceable. --(++r) == r. --r == --s implies r == s. addressof(r) == addressof(--r).
🔗 r-- convertible to const X& { X tmp = r; --r; return tmp; }
🔗 *r-- reference

[Note 1:

Bidirectional iterators allow algorithms to move iterators backward as well as forward.

— _end note_]

23.3.5.7 Random access iterators [random.access.iterators]

A class or pointer typeXmeets the requirements of a random access iterator if, in addition to meeting the Cpp17BidirectionalIterator requirements, the following expressions are valid as shown in Table 89.

Table 89: Cpp17RandomAccessIterator requirements (in addition to Cpp17BidirectionalIterator) [tab:randomaccessiterator]

🔗 Expression Return type Operational Assertion/note
🔗 semantics pre-/post-condition
🔗 r += n X& { difference_­type m = n; if (m >= 0) while (m--) ++r; else while (m++) --r; return r; }
🔗 a + nn + a X { X tmp = a; return tmp += n; } a + n == n + a.
🔗 r -= n X& return r += -n; Preconditions: the absolute value of n is in the range of representable values of difference_­type.
🔗 a - n X { X tmp = a; return tmp -= n; }
🔗 b - a difference_­type return n Preconditions: there exists a value n of type difference_­type such that a + n == b. b == a + (b - a).
🔗 a[n] convertible to reference *(a + n)
🔗 a < b contextually convertible to bool b - a > 0 < is a total ordering relation
🔗 a > b contextually convertible to bool b < a > is a total ordering relation opposite to <.
🔗 a >= b contextually convertible to bool !(a < b)
🔗 a <= b contextually convertible to bool. !(a > b)

23.3.6 Indirect callable requirements [indirectcallable]

23.3.6.2 Indirect callables [indirectcallable.indirectinvocable]

The indirect callable concepts are used to constrain those algorithms that accept callable objects ([func.def]) as arguments.

namespace std { template<class F, class I> concept indirectly_­unary_­invocable = indirectly_­readable<I> && copy_­constructible<F> && invocable<F&, iter_value_t<I>&> && invocable<F&, iter_reference_t<I>> && invocable<F&, iter_common_reference_t<I>> && common_reference_with< invoke_result_t<F&, iter_value_t<I>&>, invoke_result_t<F&, iter_reference_t<I>>>;template<class F, class I> concept indirectly_­regular_­unary_­invocable = indirectly_­readable<I> && copy_­constructible<F> && regular_­invocable<F&, iter_value_t<I>&> && regular_­invocable<F&, iter_reference_t<I>> && regular_­invocable<F&, iter_common_reference_t<I>> && common_reference_with< invoke_result_t<F&, iter_value_t<I>&>, invoke_result_t<F&, iter_reference_t<I>>>;template<class F, class I> concept indirect_­unary_­predicate = indirectly_­readable<I> && copy_­constructible<F> && predicate<F&, iter_value_t<I>&> && predicate<F&, iter_reference_t<I>> && predicate<F&, iter_common_reference_t<I>>;template<class F, class I1, class I2> concept indirect_­binary_­predicate = indirectly_­readable<I1> && indirectly_­readable<I2> && copy_­constructible<F> && predicate<F&, iter_value_t<I1>&, iter_value_t<I2>&> && predicate<F&, iter_value_t<I1>&, iter_reference_t<I2>> && predicate<F&, iter_reference_t<I1>, iter_value_t<I2>&> && predicate<F&, iter_reference_t<I1>, iter_reference_t<I2>> && predicate<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;template<class F, class I1, class I2 = I1> concept indirect_­equivalence_­relation = indirectly_­readable<I1> && indirectly_­readable<I2> && copy_­constructible<F> && equivalence_­relation<F&, iter_value_t<I1>&, iter_value_t<I2>&> && equivalence_­relation<F&, iter_value_t<I1>&, iter_reference_t<I2>> && equivalence_­relation<F&, iter_reference_t<I1>, iter_value_t<I2>&> && equivalence_­relation<F&, iter_reference_t<I1>, iter_reference_t<I2>> && equivalence_­relation<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;template<class F, class I1, class I2 = I1> concept indirect_­strict_­weak_­order = indirectly_­readable<I1> && indirectly_­readable<I2> && copy_­constructible<F> && strict_­weak_­order<F&, iter_value_t<I1>&, iter_value_t<I2>&> && strict_­weak_­order<F&, iter_value_t<I1>&, iter_reference_t<I2>> && strict_­weak_­order<F&, iter_reference_t<I1>, iter_value_t<I2>&> && strict_­weak_­order<F&, iter_reference_t<I1>, iter_reference_t<I2>> && strict_­weak_­order<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;}

23.3.6.3 Class template projected [projected]

Class template projected is used to constrain algorithms that accept callable objects and projections ([defns.projection]).

It combines a indirectly_­readable type I and a callable object type Proj into a new indirectly_­readable type whose reference type is the result of applyingProj to the iter_­reference_­t of I.

namespace std { template<indirectly_­readable I, indirectly_­regular_­unary_­invocable<I> Proj> struct projected { using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>; indirect_result_t<Proj&, I> operator*() const; };template<weakly_­incrementable I, class Proj> struct incrementable_traits<projected<I, Proj>> { using difference_type = iter_difference_t<I>;};}

23.3.7 Common algorithm requirements [alg.req]

23.3.7.1 General [alg.req.general]

There are several additional iterator concepts that are commonly applied to families of algorithms.

These group together iterator requirements of algorithm families.

There are three relational concepts that specify how element values are transferred betweenindirectly_­readable and indirectly_­writable types:indirectly_­movable,indirectly_­copyable, andindirectly_­swappable.

There are three relational concepts for rearrangements:permutable,mergeable, andsortable.

There is one relational concept for comparing values from different sequences:indirectly_­comparable.

[Note 1:

The ranges​::​less function object type used in the concepts below imposes constraints on the concepts' arguments in addition to those that appear in the concepts' bodies ([range.cmp]).

— _end note_]

23.3.7.2 Concept indirectly_­movable [alg.req.ind.move]

The indirectly_­movable concept specifies the relationship between a indirectly_­readable type and a indirectly_­writable type between which values may be moved.

template<class In, class Out> concept indirectly_­movable = indirectly_­readable<In> && indirectly_­writable<Out, iter_rvalue_reference_t<In>>;

The indirectly_­movable_­storable concept augmentsindirectly_­movable with additional requirements enabling the transfer to be performed through an intermediate object of theindirectly_­readable type's value type.

template<class In, class Out> concept indirectly_­movable_­storable = indirectly_­movable<In, Out> && indirectly_­writable<Out, iter_value_t<In>> && movable<iter_value_t<In>> && constructible_­from<iter_value_t<In>, iter_rvalue_reference_t<In>> && assignable_­from<iter_value_t<In>&, iter_rvalue_reference_t<In>>;

Let i be a dereferenceable value of type In.

In and Out model indirectly_­movable_­storable<In, Out>only if after the initialization of the object obj initer_value_t<In> obj(ranges::iter_move(i)); obj is equal to the value previously denoted by *i.

Ifiter_­rvalue_­reference_­t<In> is an rvalue reference type, the resulting state of the value denoted by *i is valid but unspecified ([lib.types.movedfrom]).

23.3.7.3 Concept indirectly_­copyable [alg.req.ind.copy]

The indirectly_­copyable concept specifies the relationship between a indirectly_­readable type and a indirectly_­writable type between which values may be copied.

template<class In, class Out> concept indirectly_­copyable = indirectly_­readable<In> && indirectly_­writable<Out, iter_reference_t<In>>;

The indirectly_­copyable_­storable concept augmentsindirectly_­copyable with additional requirements enabling the transfer to be performed through an intermediate object of theindirectly_­readable type's value type.

It also requires the capability to make copies of values.

template<class In, class Out> concept indirectly_­copyable_­storable = indirectly_­copyable<In, Out> && indirectly_­writable<Out, iter_value_t<In>&> && indirectly_­writable<Out, const iter_value_t<In>&> && indirectly_­writable<Out, iter_value_t<In>&&> && indirectly_­writable<Out, const iter_value_t<In>&&> && copyable<iter_value_t<In>> && constructible_­from<iter_value_t<In>, iter_reference_t<In>> && assignable_­from<iter_value_t<In>&, iter_reference_t<In>>;

Let i be a dereferenceable value of type In.

In and Out model indirectly_­copyable_­storable<In, Out>only if after the initialization of the object obj initer_value_t<In> obj(*i); obj is equal to the value previously denoted by *i.

Ifiter_­reference_­t<In> is an rvalue reference type, the resulting state of the value denoted by *i is valid but unspecified ([lib.types.movedfrom]).

23.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]

The indirectly_­swappable concept specifies a swappable relationship between the values referenced by two indirectly_­readable types.

template<class I1, class I2 = I1> concept indirectly_­swappable = indirectly_­readable<I1> && indirectly_­readable<I2> && requires(const I1 i1, const I2 i2) { ranges::iter_swap(i1, i1); ranges::iter_swap(i2, i2); ranges::iter_swap(i1, i2); ranges::iter_swap(i2, i1);};

23.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]

The indirectly_­comparable concept specifies the common requirements of algorithms that compare values from two different sequences.

template<class I1, class I2, class R, class P1 = identity,class P2 = identity> concept indirectly_­comparable = indirect_­binary_­predicate<R, projected<I1, P1>, projected<I2, P2>>;

23.3.7.6 Concept permutable [alg.req.permutable]

The permutable concept specifies the common requirements of algorithms that reorder elements in place by moving or swapping them.

template<class I> concept permutable = forward_­iterator<I> && indirectly_­movable_­storable<I, I> && indirectly_­swappable<I, I>;

23.3.7.7 Concept mergeable [alg.req.mergeable]

The mergeable concept specifies the requirements of algorithms that merge sorted sequences into an output sequence by copying elements.

template<class I1, class I2, class Out, class R = ranges::less,class P1 = identity, class P2 = identity> concept mergeable = input_­iterator<I1> && input_­iterator<I2> && weakly_­incrementable<Out> && indirectly_­copyable<I1, Out> && indirectly_­copyable<I2, Out> && indirect_­strict_­weak_­order<R, projected<I1, P1>, projected<I2, P2>>;

23.3.7.8 Concept sortable [alg.req.sortable]

The sortable concept specifies the common requirements of algorithms that permute sequences into ordered sequences (e.g., sort).

template<class I, class R = ranges::less, class P = identity> concept sortable = permutable<I> && indirect_­strict_­weak_­order<R, projected<I, P>>;

23.4 Iterator primitives [iterator.primitives]

23.4.3 Iterator operations [iterator.operations]

Since only random access iterators provide+and-operators, the library provides two function templatesadvanceanddistance.

These function templates use+and-for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use++to provide linear time implementations.

template<class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n);

Preconditions: nis negative only for bidirectional iterators.

Effects: Increments i by n if n is non-negative, and decrements i by -n otherwise.

template<class InputIterator> constexpr typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last);

Preconditions: last is reachable from first, orInputIterator meets the Cpp17RandomAccessIterator requirements andfirst is reachable from last.

Effects: If InputIterator meets the Cpp17RandomAccessIterator requirements, returns (last - first); otherwise, returns the number of increments needed to get fromfirsttolast.

template<class InputIterator> constexpr InputIterator next(InputIterator x,typename iterator_traits<InputIterator>::difference_type n = 1);

Effects: Equivalent to: advance(x, n); return x;

template<class BidirectionalIterator> constexpr BidirectionalIterator prev(BidirectionalIterator x,typename iterator_traits<BidirectionalIterator>::difference_type n = 1);

Effects: Equivalent to: advance(x, -n); return x;

23.4.4 Range iterator operations [range.iter.ops]

23.4.4.1 General [range.iter.ops.general]

The library includes the function templatesranges​::​advance, ranges​::​distance,ranges​::​next, and ranges​::​prevto manipulate iterators.

These operations adapt to the set of operators provided by each iterator category to provide the most efficient implementation possible for a concrete iterator type.

[Example 1:

ranges​::​advance uses the + operator to move arandom_­access_­iterator forward n steps in constant time.

For an iterator type that does not model random_­access_­iterator,ranges​::​advance instead performs n individual increments with the ++ operator.

— _end example_]

[Example 2: void foo() { using namespace std::ranges; std::vector<int> vec{1,2,3}; distance(begin(vec), end(vec)); }

The function call expression at #1 invokes std​::​ranges​::​distance, not std​::​distance, despite that (a) the iterator type returned from begin(vec) and end(vec)may be associated with namespace std and (b) std​::​distance is more specialized ([temp.func.order]) thanstd​::​ranges​::​distance since the former requires its first two parameters to have the same type.

— _end example_]

The number and order of deducible template parameters for the function templates defined in [range.iter.ops] is unspecified, except where explicitly stated otherwise.

23.4.4.2 ranges​::​advance [range.iter.op.advance]

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I> constexpr void ranges::advance(I& i, iter_difference_t<I> n);

Preconditions: If I does not model bidirectional_­iterator,n is not negative.

Effects:

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S> constexpr void ranges::advance(I& i, S bound);

Preconditions: [i, bound) denotes a range.

Effects:

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S> constexpr iter_difference_t<I> ranges::advance(I& i, iter_difference_t<I> n, S bound);

Preconditions: If n > 0, [i, bound) denotes a range.

If n == 0, [i, bound) or [bound, i) denotes a range.

If n < 0, [bound, i) denotes a range,I models bidirectional_­iterator, andI and S model same_­as<I, S>.

Effects:

Returns: n - M, where M is the difference between the ending and starting positions of i.

23.4.4.3 ranges​::​distance [range.iter.op.distance]

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S> constexpr iter_difference_t<I> ranges::distance(I first, S last);

Preconditions: [first, last) denotes a range, or [last, first) denotes a range andS and I modelsame_­as<S, I> && sized_­sentinel_­for<S, I>.

Effects: If S and I model sized_­sentinel_­for<S, I>, returns (last - first); otherwise, returns the number of increments needed to get fromfirsttolast.

template<[range](range.range#concept:range "24.4.2 Ranges [range.range]") R> constexpr range_difference_t<R> ranges::distance(R&& r);

Effects: If R models sized_­range, equivalent to:return static_cast<range_difference_t<R>>(ranges::size(r));

Otherwise, equivalent to:return ranges::distance(ranges::begin(r), ranges::end(r));

23.4.4.4 ranges​::​next [range.iter.op.next]

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I> constexpr I ranges::next(I x);

Effects: Equivalent to: ++x; return x;

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I> constexpr I ranges::next(I x, iter_difference_t<I> n);

Effects: Equivalent to: ranges​::​advance(x, n); return x;

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S> constexpr I ranges::next(I x, S bound);

Effects: Equivalent to: ranges​::​advance(x, bound); return x;

template<[input_­or_­output_­iterator](#concept:input%5For%5Foutput%5Fiterator "23.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S> constexpr I ranges::next(I x, iter_difference_t<I> n, S bound);

Effects: Equivalent to: ranges​::​advance(x, n, bound); return x;

23.4.4.5 ranges​::​prev [range.iter.op.prev]

template<[bidirectional_­iterator](#concept:bidirectional%5Fiterator "23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]") I> constexpr I ranges::prev(I x);

Effects: Equivalent to: --x; return x;

template<[bidirectional_­iterator](#concept:bidirectional%5Fiterator "23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]") I> constexpr I ranges::prev(I x, iter_difference_t<I> n);

Effects: Equivalent to: ranges​::​advance(x, -n); return x;

template<[bidirectional_­iterator](#concept:bidirectional%5Fiterator "23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]") I> constexpr I ranges::prev(I x, iter_difference_t<I> n, I bound);

Effects: Equivalent to: ranges​::​advance(x, -n, bound); return x;

23.5 Iterator adaptors [predef.iterators]

23.5.1 Reverse iterators [reverse.iterators]

23.5.1.1 General [reverse.iterators.general]

Class template reverse_­iterator is an iterator adaptor that iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence.

23.5.1.2 Class template reverse_­iterator [reverse.iterator]

namespace std { template<class Iterator> class reverse_iterator { public: using iterator_type = Iterator;using iterator_concept = see below;using iterator_category = see below;using value_type = iter_value_t<Iterator>;using difference_type = iter_difference_t<Iterator>;using pointer = typename iterator_traits<Iterator>::pointer;using reference = iter_reference_t<Iterator>;constexpr reverse_iterator();constexpr explicit reverse_iterator(Iterator x);template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);template<class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);constexpr Iterator base() const;constexpr reference operator*() const;constexpr pointer operator->() const requires see below;constexpr reverse_iterator& operator++();constexpr reverse_iterator operator++(int);constexpr reverse_iterator& operator--();constexpr reverse_iterator operator--(int);constexpr reverse_iterator operator+ (difference_type n) const;constexpr reverse_iterator& operator+=(difference_type n);constexpr reverse_iterator operator- (difference_type n) const;constexpr reverse_iterator& operator-=(difference_type n);constexpr unspecified operator[](difference_type n) const;friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const reverse_iterator& i) noexcept(see below);template<indirectly_­swappable<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x,const reverse_iterator<Iterator2>& y) noexcept(see below);protected: Iterator current;};}

The member typedef-name iterator_­concept denotes

The member typedef-name iterator_­category denotes

23.5.1.3 Requirements [reverse.iter.requirements]

The template parameterIteratorshall either meet the requirements of a_Cpp17BidirectionalIterator_ ([bidirectional.iterators]) or modelbidirectional_­iterator ([iterator.concept.bidir]).

Additionally,Iteratorshall either meet the requirements of a_Cpp17RandomAccessIterator_ ([random.access.iterators]) or modelrandom_­access_­iterator ([iterator.concept.random.access]) if the definitions of any of the members

or the non-member operators ([reverse.iter.cmp])

are instantiated ([temp.inst]).

23.5.1.4 Construction and assignment [reverse.iter.cons]

constexpr reverse_iterator();

Effects: Value-initializescurrent.

Iterator operations applied to the resulting iterator have defined behavior if and only if the corresponding operations are defined on a value-initialized iterator of typeIterator.

constexpr explicit reverse_iterator(Iterator x);

Effects: Initializescurrentwith x.

template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);

Effects: Initializescurrentwithu.current.

template<class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);

Effects: Assigns u.base() to current.

23.5.1.6 Element access [reverse.iter.elem]

constexpr reference operator*() const;

Effects: As if by:Iterator tmp = current;return *--tmp;

constexpr pointer operator->() const requires (is_pointer_v<Iterator> || requires (const Iterator i) { i.operator->(); });

Effects:

constexpr _unspecified_ operator[](difference_type n) const;

23.5.1.7 Navigation [reverse.iter.nav]

constexpr reverse_iterator operator+(difference_type n) const;

Returns: reverse_­iterator(current-n).

constexpr reverse_iterator operator-(difference_type n) const;

Returns: reverse_­iterator(current+n).

constexpr reverse_iterator& operator++();

Effects: As if by: --current;

constexpr reverse_iterator operator++(int);

Effects: As if by:reverse_iterator tmp = *this;--current;return tmp;

constexpr reverse_iterator& operator--();

Effects: As if by ++current.

constexpr reverse_iterator operator--(int);

Effects: As if by:reverse_iterator tmp = *this;++current;return tmp;

constexpr reverse_iterator& operator+=(difference_type n);

Effects: As if by: current -= n;

constexpr reverse_iterator& operator-=(difference_type n);

Effects: As if by: current += n;

23.5.1.8 Comparisons [reverse.iter.cmp]

template<class Iterator1, class Iterator2> constexpr bool operator==( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() == y.base() is well-formed and convertible to bool.

Returns: x.base() == y.base().

template<class Iterator1, class Iterator2> constexpr bool operator!=( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() != y.base() is well-formed and convertible to bool.

Returns: x.base() != y.base().

template<class Iterator1, class Iterator2> constexpr bool operator<( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() > y.base() is well-formed and convertible to bool.

Returns: x.base() > y.base().

template<class Iterator1, class Iterator2> constexpr bool operator>( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() < y.base() is well-formed and convertible to bool.

Returns: x.base() < y.base().

template<class Iterator1, class Iterator2> constexpr bool operator<=( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() >= y.base() is well-formed and convertible to bool.

Returns: x.base() >= y.base().

template<class Iterator1, class Iterator2> constexpr bool operator>=( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() <= y.base() is well-formed and convertible to bool.

Returns: x.base() <= y.base().

template<class Iterator1, [three_­way_­comparable_­with](cmp.concept#concept:three%5Fway%5Fcomparable%5Fwith "17.11.4 Concept three_­way_­comparable [cmp.concept]")<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Returns: y.base() <=> x.base().

[Note 1:

The argument order in the Returns: element is reversed because this is a reverse iterator.

— _end note_]

23.5.1.9 Non-member functions [reverse.iter.nonmember]

template<class Iterator1, class Iterator2> constexpr auto operator-( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());

Returns: y.base() - x.base().

template<class Iterator> constexpr reverse_iterator<Iterator> operator+( iter_difference_t<Iterator> n,const reverse_iterator<Iterator>& x);

Returns: reverse_­iterator<Iterator>(x.base() - n).

friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const reverse_iterator& i) noexcept(_see below_);

Effects: Equivalent to:auto tmp = i.base();return ranges::iter_move(--tmp);

Remarks: The expression in noexcept is equivalent to:is_nothrow_copy_constructible_v<Iterator> && noexcept(ranges::iter_move(--declval<Iterator&>()))

template<[indirectly_­swappable](#concept:indirectly%5Fswappable "23.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x,const reverse_iterator<Iterator2>& y) noexcept(_see below_);

Effects: Equivalent to:auto xtmp = x.base();auto ytmp = y.base(); ranges::iter_swap(--xtmp, --ytmp);

Remarks: The expression in noexcept is equivalent to:is_nothrow_copy_constructible_v<Iterator> &&is_nothrow_copy_constructible_v<Iterator2> && noexcept(ranges::iter_swap(--declval<Iterator&>(), --declval<Iterator2&>()))

template<class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);

Returns: reverse_­iterator<Iterator>(i).

23.5.2 Insert iterators [insert.iterators]

23.5.2.1 General [insert.iterators.general]

To make it possible to deal with insertion in the same way as writing into an array, a special kind of iterator adaptors, calledinsert iterators, are provided in the library.

With regular iterator classes,while (first != last) *result++ = *first++;causes a range [first, last) to be copied into a range starting with result.

The same code withresultbeing an insert iterator will insert corresponding elements into the container.

This device allows all of the copying algorithms in the library to work in theinsert modeinstead of the regular overwrite mode.

An insert iterator is constructed from a container and possibly one of its iterators pointing to where insertion takes place if it is neither at the beginning nor at the end of the container.

Insert iterators meet the requirements of output iterators.

operator*returns the insert iterator itself.

The assignmentoperator=(const T& x)is defined on insert iterators to allow writing into them, it insertsxright before where the insert iterator is pointing.

In other words, an insert iterator is like a cursor pointing into the container where the insertion takes place.

back_­insert_­iteratorinserts elements at the end of a container,front_­insert_­iteratorinserts elements at the beginning of a container, andinsert_­iteratorinserts elements where the iterator points to in a container.

back_­inserter,front_­inserter, andinserterare three functions making the insert iterators out of a container.

23.5.2.2 Class template back_­insert_­iterator [back.insert.iterator]

namespace std { template<class Container> class back_insert_iterator { protected: Container* container = nullptr;public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using container_type = Container;constexpr back_insert_iterator() noexcept = default;constexpr explicit back_insert_iterator(Container& x);constexpr back_insert_iterator& operator=(const typename Container::value_type& value);constexpr back_insert_iterator& operator=(typename Container::value_type&& value);constexpr back_insert_iterator& operator*();constexpr back_insert_iterator& operator++();constexpr back_insert_iterator operator++(int);};}

23.5.2.2.1 Operations [back.insert.iter.ops]

constexpr explicit back_insert_iterator(Container& x);

Effects: Initializescontainerwith addressof(x).

constexpr back_insert_iterator& operator=(const typename Container::value_type& value);

Effects: As if by: container->push_­back(value);

constexpr back_insert_iterator& operator=(typename Container::value_type&& value);

Effects: As if by: container->push_­back(std​::​move(value));

constexpr back_insert_iterator& operator*();

constexpr back_insert_iterator& operator++();constexpr back_insert_iterator operator++(int);

23.5.2.2.2 back_­inserter [back.inserter]

template<class Container> constexpr back_insert_iterator<Container> back_inserter(Container& x);

Returns: back_­insert_­iterator<Container>(x).

23.5.2.3 Class template front_­insert_­iterator [front.insert.iterator]

namespace std { template<class Container> class front_insert_iterator { protected: Container* container = nullptr;public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using container_type = Container;constexpr front_insert_iterator() noexcept = default;constexpr explicit front_insert_iterator(Container& x);constexpr front_insert_iterator& operator=(const typename Container::value_type& value);constexpr front_insert_iterator& operator=(typename Container::value_type&& value);constexpr front_insert_iterator& operator*();constexpr front_insert_iterator& operator++();constexpr front_insert_iterator operator++(int);};}

23.5.2.3.1 Operations [front.insert.iter.ops]

constexpr explicit front_insert_iterator(Container& x);

Effects: Initializescontainerwith addressof(x).

constexpr front_insert_iterator& operator=(const typename Container::value_type& value);

Effects: As if by: container->push_­front(value);

constexpr front_insert_iterator& operator=(typename Container::value_type&& value);

Effects: As if by: container->push_­front(std​::​move(value));

constexpr front_insert_iterator& operator*();

constexpr front_insert_iterator& operator++();constexpr front_insert_iterator operator++(int);

23.5.2.3.2 front_­inserter [front.inserter]

template<class Container> constexpr front_insert_iterator<Container> front_inserter(Container& x);

Returns: front_­insert_­iterator<Container>(x).

23.5.2.4 Class template insert_­iterator [insert.iterator]

namespace std { template<class Container> class insert_iterator { protected: Container* container = nullptr; ranges::iterator_t<Container> iter = ranges::iterator_t<Container>();public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using container_type = Container; insert_iterator() = default;constexpr insert_iterator(Container& x, ranges::iterator_t<Container> i);constexpr insert_iterator& operator=(const typename Container::value_type& value);constexpr insert_iterator& operator=(typename Container::value_type&& value);constexpr insert_iterator& operator*();constexpr insert_iterator& operator++();constexpr insert_iterator& operator++(int);};}

23.5.2.4.1 Operations [insert.iter.ops]

constexpr insert_iterator(Container& x, ranges::iterator_t<Container> i);

Effects: Initializescontainerwith addressof(x) anditerwith i.

constexpr insert_iterator& operator=(const typename Container::value_type& value);

Effects: As if by:iter = container->insert(iter, value);++iter;

constexpr insert_iterator& operator=(typename Container::value_type&& value);

Effects: As if by:iter = container->insert(iter, std::move(value));++iter;

constexpr insert_iterator& operator*();

constexpr insert_iterator& operator++();constexpr insert_iterator& operator++(int);

23.5.2.4.2 inserter [inserter]

template<class Container> constexpr insert_iterator<Container> inserter(Container& x, ranges::iterator_t<Container> i);

Returns: insert_­iterator<Container>(x, i).

23.5.3 Move iterators and sentinels [move.iterators]

23.5.3.1 General [move.iterators.general]

Class template move_­iterator is an iterator adaptor with the same behavior as the underlying iterator except that its indirection operator implicitly converts the value returned by the underlying iterator's indirection operator to an rvalue.

Some generic algorithms can be called with move iterators to replace copying with moving.

[Example 1: list<string> s; vector<string> v1(s.begin(), s.end()); vector<string> v2(make_move_iterator(s.begin()), make_move_iterator(s.end())); — _end example_]

23.5.3.2 Class template move_­iterator [move.iterator]

namespace std { template<class Iterator> class move_iterator { public: using iterator_type = Iterator;using iterator_concept = input_iterator_tag;using iterator_category = see below;using value_type = iter_value_t<Iterator>;using difference_type = iter_difference_t<Iterator>;using pointer = Iterator;using reference = iter_rvalue_reference_t<Iterator>;constexpr move_iterator();constexpr explicit move_iterator(Iterator i);template<class U> constexpr move_iterator(const move_iterator<U>& u);template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);constexpr iterator_type base() const &;constexpr iterator_type base() &&;constexpr reference operator*() const;constexpr move_iterator& operator++();constexpr auto operator++(int);constexpr move_iterator& operator--();constexpr move_iterator operator--(int);constexpr move_iterator operator+(difference_type n) const;constexpr move_iterator& operator+=(difference_type n);constexpr move_iterator operator-(difference_type n) const;constexpr move_iterator& operator-=(difference_type n);constexpr reference operator[](difference_type n) const;template<sentinel_­for<Iterator> S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel<S>& y);template<sized_­sentinel_­for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y);template<sized_­sentinel_­for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_iterator& x, const move_sentinel<S>& y);friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const move_iterator& i) noexcept(noexcept(ranges::iter_move(i.current)));template<indirectly_­swappable<Iterator> Iterator2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));private: Iterator current; };}

The member typedef-name iterator_­category denotes

23.5.3.3 Requirements [move.iter.requirements]

The template parameter Iterator shall either meet the Cpp17InputIterator requirements ([input.iterators]) or model input_­iterator ([iterator.concept.input]).

Additionally, if any of the bidirectional traversal functions are instantiated, the template parameter shall either meet the Cpp17BidirectionalIterator requirements ([bidirectional.iterators]) or model bidirectional_­iterator ([iterator.concept.bidir]).

If any of the random access traversal functions are instantiated, the template parameter shall either meet the Cpp17RandomAccessIterator requirements ([random.access.iterators]) or modelrandom_­access_­iterator ([iterator.concept.random.access]).

23.5.3.4 Construction and assignment [move.iter.cons]

constexpr move_iterator();

Effects: Constructs a move_­iterator, value-initializingcurrent.

Iterator operations applied to the resulting iterator have defined behavior if and only if the corresponding operations are defined on a value-initialized iterator of type Iterator.

constexpr explicit move_iterator(Iterator i);

Effects: Constructs a move_­iterator, initializingcurrent with std​::​move(i).

template<class U> constexpr move_iterator(const move_iterator<U>& u);

Mandates: U is convertible to Iterator.

Effects: Constructs a move_­iterator, initializingcurrent with u.base().

template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);

Mandates: U is convertible to Iterator.

Effects: Assigns u.base() tocurrent.

23.5.3.5 Conversion [move.iter.op.conv]

constexpr Iterator base() const &;

constexpr Iterator base() &&;

Returns: std​::​move(current).

23.5.3.6 Element access [move.iter.elem]

constexpr reference operator*() const;

Effects: Equivalent to: return ranges​::​iter_­move(current);

constexpr reference operator[](difference_type n) const;

Effects: Equivalent to: return ranges​::​iter_­move(current + n);

23.5.3.7 Navigation [move.iter.nav]

constexpr move_iterator& operator++();

Effects: As if by ++current.

constexpr auto operator++(int);

Effects: If Iterator models forward_­iterator, equivalent to:move_iterator tmp = *this;++current;return tmp;

Otherwise, equivalent to ++current.

constexpr move_iterator& operator--();

Effects: As if by --current.

constexpr move_iterator operator--(int);

Effects: As if by:move_iterator tmp = *this;--current;return tmp;

constexpr move_iterator operator+(difference_type n) const;

Returns: move_­iterator(current + n).

constexpr move_iterator& operator+=(difference_type n);

Effects: As if by: current += n;

constexpr move_iterator operator-(difference_type n) const;

Returns: move_­iterator(current - n).

constexpr move_iterator& operator-=(difference_type n);

Effects: As if by: current -= n;

23.5.3.8 Comparisons [move.iter.op.comp]

template<class Iterator1, class Iterator2> constexpr bool operator==(const move_iterator<Iterator1>& x,const move_iterator<Iterator2>& y);template<[sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<Iterator> S> friend constexpr bool operator==(const move_iterator& x,const move_sentinel<S>& y);

Constraints: x.base() == y.base() is well-formed and convertible to bool.

Returns: x.base() == y.base().

template<class Iterator1, class Iterator2> constexpr bool operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Constraints: x.base() < y.base() is well-formed and convertible to bool.

Returns: x.base() < y.base().

template<class Iterator1, class Iterator2> constexpr bool operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Constraints: y.base() < x.base() is well-formed and convertible to bool.

template<class Iterator1, class Iterator2> constexpr bool operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Constraints: y.base() < x.base() is well-formed and convertible to bool.

template<class Iterator1, class Iterator2> constexpr bool operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Constraints: x.base() < y.base() is well-formed and convertible to bool.

template<class Iterator1, [three_­way_­comparable_­with](cmp.concept#concept:three%5Fway%5Fcomparable%5Fwith "17.11.4 Concept three_­way_­comparable [cmp.concept]")<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const move_iterator<Iterator1>& x,const move_iterator<Iterator2>& y);

Returns: x.base() <=> y.base().

23.5.3.9 Non-member functions [move.iter.nonmember]

template<class Iterator1, class Iterator2> constexpr auto operator-( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base());template<[sized_­sentinel_­for](#concept:sized%5Fsentinel%5Ffor "23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y);template<[sized_­sentinel_­for](#concept:sized%5Fsentinel%5Ffor "23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_iterator& x, const move_sentinel<S>& y);

Returns: x.base() - y.base().

template<class Iterator> constexpr move_iterator<Iterator> operator+(iter_difference_t<Iterator> n, const move_iterator<Iterator>& x);

Constraints: x + n is well-formed and has type Iterator.

friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const move_iterator& i) noexcept(noexcept(ranges::iter_move(i.current)));

Effects: Equivalent to: return ranges​::​iter_­move(i.current);

template<[indirectly_­swappable](#concept:indirectly%5Fswappable "23.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<Iterator> Iterator2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));

Effects: Equivalent to: ranges​::​iter_­swap(x.current, y.current).

template<class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i);

Returns: move_­iterator<Iterator>(std​::​move(i)).

23.5.3.10 Class template move_­sentinel [move.sentinel]

Class template move_­sentinel is a sentinel adaptor useful for denoting ranges together with move_­iterator.

When an input iterator typeI and sentinel type S model sentinel_­for<S, I>,move_­sentinel<S> and move_­iterator<I> modelsentinel_­for<move_­sentinel<S>, move_­iterator<I>> as well.

[Example 1:

A move_­if algorithm is easily implemented withcopy_­if using move_­iterator and move_­sentinel:template<input_­iterator I, sentinel_­for<I> S, weakly_­incrementable O,indirect_­unary_­predicate<I> Pred> requires indirectly_­movable<I, O> void move_if(I first, S last, O out, Pred pred) { std::ranges::copy_if(move_iterator<I>{first}, move_sentinel<S>{last}, out, pred);}

— _end example_]

namespace std { template<semiregular S> class move_sentinel { public: constexpr move_sentinel();constexpr explicit move_sentinel(S s);template<class S2> requires convertible_­to<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s);template<class S2> requires assignable_­from<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s);constexpr S base() const;private: S last; };}

23.5.3.11 Operations [move.sent.ops]

constexpr move_sentinel();

Effects: Value-initializes last.

If is_­trivially_­default_­constructible_­v<S> is true, then this constructor is a constexpr constructor.

constexpr explicit move_sentinel(S s);

Effects: Initializes last with std​::​move(s).

template<class S2> requires [convertible_­to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s);

Effects: Initializes last with s.last.

template<class S2> requires [assignable_­from](concept.assignable#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s);

Effects: Equivalent to: last = s.last; return *this;

constexpr S base() const;

23.5.4 Common iterators [iterators.common]

23.5.4.1 Class template common_­iterator [common.iterator]

Class template common_­iterator is an iterator/sentinel adaptor that is capable of representing a non-common range of elements (where the types of the iterator and sentinel differ) as a common range (where they are the same).

It does this by holding either an iterator or a sentinel, and implementing the equality comparison operators appropriately.

[Note 1:

The common_­iterator type is useful for interfacing with legacy code that expects the begin and end of a range to have the same type.

— _end note_]

[Example 1: template<class ForwardIterator> void fun(ForwardIterator begin, ForwardIterator end); list<int> s;using CI = common_iterator<counted_iterator<list<int>::iterator>, default_sentinel_t>; fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel)); — _end example_]

namespace std { template<input_­or_­output_­iterator I, sentinel_­for<I> S> requires (same\_­as<I, S> && copyable<I>) class common_iterator { public: constexpr common_iterator() = default;constexpr common_iterator(I i);constexpr common_iterator(S s);template<class I2, class S2> requires convertible_­to<const I2&, I> && convertible_­to<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);template<class I2, class S2> requires convertible_­to<const I2&, I> && convertible_­to<const S2&, S> && assignable_­from<I&, const I2&> && assignable_­from<S&, const S2&> common_iterator& operator=(const common_iterator<I2, S2>& x);decltype(auto) operator*();decltype(auto) operator*() const requires dereferenceable<const I>;decltype(auto) operator->() const requires see below; common_iterator& operator++();decltype(auto) operator++(int);template<class I2, sentinel_­for<I> S2> requires sentinel_­for<S, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);template<class I2, sentinel_­for<I> S2> requires sentinel_­for<S, I2> && equality_comparable_with<I, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);template<sized_­sentinel_­for<I> I2, sized_­sentinel_­for<I> S2> requires sized_­sentinel_­for<S, I2> friend iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y);friend iter_rvalue_reference_t<I> iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires input_­iterator<I>;template<indirectly_­swappable<I> I2, class S2> friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));private: variant<I, S> v_; };template<class I, class S> struct incrementable_traits<common_iterator<I, S>> { using difference_type = iter_difference_t<I>;};template<input_­iterator I, class S> struct iterator_traits<common_iterator<I, S>> { using iterator_concept = see below;using iterator_category = see below;using value_type = iter_value_t<I>;using difference_type = iter_difference_t<I>;using pointer = see below;using reference = iter_reference_t<I>;};}

23.5.4.2 Associated types [common.iter.types]

The nested typedef-names of the specialization ofiterator_­traits for common_­iterator<I, S> are defined as follows.

23.5.4.3 Constructors and conversions [common.iter.const]

constexpr common_iterator(I i);

Effects: Initializes v_­ as if by v_­{in_­place_­type<I>, std​::​move(i)}.

constexpr common_iterator(S s);

Effects: Initializes v_­ as if byv_­{in_­place_­type<S>, std​::​move(s)}.

template<class I2, class S2> requires [convertible_­to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const I2&, I> && [convertible_­to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);

Preconditions: x.v_­.valueless_­by_­exception() is false.

Effects: Initializes v_­ as if byv_­{in_­place_­index<i>, get<i>(x.v_­)}, where i is x.v_­.index().

Preconditions: x.v_­.valueless_­by_­exception() is false.

Effects: Equivalent to:

where i is x.v_­.index().

23.5.4.4 Accessors [common.iter.access]

decltype(auto) operator*();decltype(auto) operator*() const requires [_dereferenceable_](#concept:dereferenceable "23.2 Header <iterator> synopsis [iterator.synopsis]")<const I>;

Preconditions: holds_­alternative<I>(v_­).

Effects: Equivalent to: return *get<I>(v_­);

decltype(auto) operator->() const requires _see below_;

The expression in the requires-clause is equivalent to:indirectly_­readable<const I> && (requires(const I& i) { i.operator->(); } || is_reference_v<iter_reference_t<I>> || constructible_­from<iter_value_t<I>, iter_reference_t<I>>)

Preconditions: holds_­alternative<I>(v_­).

Effects:

23.5.4.5 Navigation [common.iter.nav]

common_iterator& operator++();

Preconditions: holds_­alternative<I>(v_­).

Effects: Equivalent to ++get<I>(v_­).

decltype(auto) operator++(int);

Preconditions: holds_­alternative<I>(v_­).

Effects: If I models forward_­iterator, equivalent to:common_iterator tmp = *this;++*this;return tmp;

Otherwise, equivalent to: return get<I>(v_­)++;

23.5.4.6 Comparisons [common.iter.cmp]

template<class I2, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S2> requires [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);

Preconditions: x.v_­.valueless_­by_­exception() and y.v_­.valueless_­by_­exception()are each false.

Returns: true if i == j, and otherwise get<i>(x.v_­) == get<j>(y.v_­), where i is x.v_­.index() and j is y.v_­.index().

template<class I2, [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S2> requires [sentinel_­for](#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I2> && equality_comparable_with<I, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);

Preconditions: x.v_­.valueless_­by_­exception() and y.v_­.valueless_­by_­exception()are each false.

Returns: true if i and j are each 1, and otherwiseget<i>(x.v_­) == get<j>(y.v_­), wherei is x.v_­.index() and j is y.v_­.index().

template<[sized_­sentinel_­for](#concept:sized%5Fsentinel%5Ffor "23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<I> I2, [sized_­sentinel_­for](#concept:sized%5Fsentinel%5Ffor "23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<I> S2> requires [sized_­sentinel_­for](#concept:sized%5Fsentinel%5Ffor "23.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<S, I2> friend iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y);

Preconditions: x.v_­.valueless_­by_­exception() and y.v_­.valueless_­by_­exception()are each false.

Returns: 0 if i and j are each 1, and otherwiseget<i>(x.v_­) - get<j>(y.v_­), wherei is x.v_­.index() and j is y.v_­.index().

23.5.4.7 Customizations [common.iter.cust]

friend iter_rvalue_reference_t<I> iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires [input_­iterator](#concept:input%5Fiterator "23.3.4.9 Concept input_­iterator [iterator.concept.input]")<I>;

Preconditions: holds_­alternative<I>(v_­).

Effects: Equivalent to: return ranges​::​iter_­move(get<I>(i.v_­));

template<[indirectly_­swappable](#concept:indirectly%5Fswappable "23.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<I> I2, class S2> friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));

Preconditions: holds_­alternative<I>(x.v_­) and holds_­alternative<I2>(y.v_­)are each true.

Effects: Equivalent to ranges​::​iter_­swap(get<I>(x.v_­), get<I2>(y.v_­)).

23.5.5 Default sentinel [default.sentinel]

namespace std { struct default_sentinel_t { };}

Class default_­sentinel_­t is an empty type used to denote the end of a range.

It can be used together with iterator types that know the bound of their range (e.g., counted_­iterator ([counted.iterator])).

23.5.6 Counted iterators [iterators.counted]

23.5.6.1 Class template counted_­iterator [counted.iterator]

Class template counted_­iterator is an iterator adaptor with the same behavior as the underlying iterator except that it keeps track of the distance to the end of its range.

It can be used together with default_­sentinelin calls to generic algorithms to operate on a range of N elements starting at a given position without needing to know the end position a priori.

[Example 1: list<string> s; vector<string> v; ranges::copy(counted_iterator(s.begin(), 10), default_sentinel, back_inserter(v)); — _end example_]

Two values i1 and i2 of typescounted_­iterator<I1>andcounted_­iterator<I2>refer to elements of the same sequence if and only ifnext(i1.base(), i1.count())andnext(i2.base(), i2.count())refer to the same (possibly past-the-end) element.

namespace std { template<input_­or_­output_­iterator I> class counted_iterator { public: using iterator_type = I;constexpr counted_iterator() = default;constexpr counted_iterator(I x, iter_difference_t<I> n);template<class I2> requires convertible_­to<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x);template<class I2> requires assignable_­from<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x);constexpr I base() const & requires copy_constructible<I>;constexpr I base() &&;constexpr iter_difference_t<I> count() const noexcept;constexpr decltype(auto) operator*();constexpr decltype(auto) operator*() const requires dereferenceable<const I>;constexpr counted_iterator& operator++();decltype(auto) operator++(int);constexpr counted_iterator operator++(int) requires forward_­iterator<I>;constexpr counted_iterator& operator--() requires bidirectional_­iterator<I>;constexpr counted_iterator operator--(int) requires bidirectional_­iterator<I>;constexpr counted_iterator operator+(iter_difference_t<I> n) const requires random_­access_­iterator<I>;friend constexpr counted_iterator operator+( iter_difference_t<I> n, const counted_iterator& x) requires random_­access_­iterator<I>;constexpr counted_iterator& operator+=(iter_difference_t<I> n) requires random_­access_­iterator<I>;constexpr counted_iterator operator-(iter_difference_t<I> n) const requires random_­access_­iterator<I>;template<common_­with<I> I2> friend constexpr iter_difference_t<I2> operator-( const counted_iterator& x, const counted_iterator<I2>& y);friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t);friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y);constexpr counted_iterator& operator-=(iter_difference_t<I> n) requires random_­access_­iterator<I>;constexpr decltype(auto) operator[](iter_difference_t<I> n) const requires random_­access_­iterator<I>;template<common_­with<I> I2> friend constexpr bool operator==( const counted_iterator& x, const counted_iterator<I2>& y);friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t);template<common_­with<I> I2> friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator<I2>& y);friend constexpr iter_rvalue_reference_t<I> iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires input_­iterator<I>;template<indirectly_­swappable<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));private: I current = I(); iter_difference_t<I> length = 0; };template<class I> struct incrementable_traits<counted_iterator<I>> { using difference_type = iter_difference_t<I>;};template<input_­iterator I> struct iterator_traits<counted_iterator<I>> : iterator_traits<I> { using pointer = void;};}

23.5.6.2 Constructors and conversions [counted.iter.const]

constexpr counted_iterator(I i, iter_difference_t<I> n);

Effects: Initializes current with std​::​move(i) andlength with n.

template<class I2> requires [convertible_­to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x);

Effects: Initializes current with x.current andlength with x.length.

template<class I2> requires [assignable_­from](concept.assignable#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x);

Effects: Assigns x.current to current andx.length to length.

23.5.6.3 Accessors [counted.iter.access]

constexpr I base() const & requires copy_constructible<I>;

Effects: Equivalent to: return current;

Returns: std​::​move(current).

constexpr iter_difference_t<I> count() const noexcept;

Effects: Equivalent to: return length;

23.5.6.4 Element access [counted.iter.elem]

constexpr decltype(auto) operator*();constexpr decltype(auto) operator*() const requires [_dereferenceable_](#concept:dereferenceable "23.2 Header <iterator> synopsis [iterator.synopsis]")<const I>;

Effects: Equivalent to: return *current;

constexpr decltype(auto) operator[](iter_difference_t<I> n) const requires [random_­access_­iterator](#concept:random%5Faccess%5Fiterator "23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Preconditions: n < length.

Effects: Equivalent to: return current[n];

23.5.6.5 Navigation [counted.iter.nav]

constexpr counted_iterator& operator++();

Preconditions: length > 0.

Effects: Equivalent to:++current;--length;return *this;

decltype(auto) operator++(int);

Preconditions: length > 0.

Effects: Equivalent to:--length;try { return current++; } catch(...) { ++length; throw; }

constexpr counted_iterator operator++(int) requires [forward_­iterator](#concept:forward%5Fiterator "23.3.4.11 Concept forward_­iterator [iterator.concept.forward]")<I>;

Effects: Equivalent to:counted_iterator tmp = *this;++*this;return tmp;

constexpr counted_iterator& operator--() requires [bidirectional_­iterator](#concept:bidirectional%5Fiterator "23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]")<I>;

Effects: Equivalent to:--current;++length;return *this;

constexpr counted_iterator operator--(int) requires [bidirectional_­iterator](#concept:bidirectional%5Fiterator "23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]")<I>;

Effects: Equivalent to:counted_iterator tmp = *this;--*this;return tmp;

constexpr counted_iterator operator+(iter_difference_t<I> n) const requires [random_­access_­iterator](#concept:random%5Faccess%5Fiterator "23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Effects: Equivalent to: return counted_­iterator(current + n, length - n);

friend constexpr counted_iterator operator+( iter_difference_t<I> n, const counted_iterator& x) requires [random_­access_­iterator](#concept:random%5Faccess%5Fiterator "23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Effects: Equivalent to: return x + n;

constexpr counted_iterator& operator+=(iter_difference_t<I> n) requires [random_­access_­iterator](#concept:random%5Faccess%5Fiterator "23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Preconditions: n <= length.

Effects: Equivalent to:current += n; length -= n;return *this;

constexpr counted_iterator operator-(iter_difference_t<I> n) const requires [random_­access_­iterator](#concept:random%5Faccess%5Fiterator "23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Effects: Equivalent to: return counted_­iterator(current - n, length + n);

template<[common_­with](concept.common#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]")<I> I2> friend constexpr iter_difference_t<I2> operator-( const counted_iterator& x, const counted_iterator<I2>& y);

Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).

Effects: Equivalent to: return y.length - x.length;

friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t);

Effects: Equivalent to:return -x.length;

friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y);

Effects: Equivalent to: return y.length;

constexpr counted_iterator& operator-=(iter_difference_t<I> n) requires [random_­access_­iterator](#concept:random%5Faccess%5Fiterator "23.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Preconditions: -n <= length.

Effects: Equivalent to:current -= n; length += n;return *this;

23.5.6.6 Comparisons [counted.iter.cmp]

template<[common_­with](concept.common#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]")<I> I2> friend constexpr bool operator==( const counted_iterator& x, const counted_iterator<I2>& y);

Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).

Effects: Equivalent to: return x.length == y.length;

friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t);

Effects: Equivalent to: return x.length == 0;

template<[common_­with](concept.common#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]")<I> I2> friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator<I2>& y);

Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).

Effects: Equivalent to: return y.length <=> x.length;

[Note 1:

The argument order in the Effects: element is reversed because length counts down, not up.

— _end note_]

23.5.6.7 Customizations [counted.iter.cust]

friend constexpr iter_rvalue_reference_t<I> iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires [input_­iterator](#concept:input%5Fiterator "23.3.4.9 Concept input_­iterator [iterator.concept.input]")<I>;

Effects: Equivalent to: return ranges​::​iter_­move(i.current);

template<[indirectly_­swappable](#concept:indirectly%5Fswappable "23.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));

Effects: Equivalent to ranges​::​iter_­swap(x.current, y.current).

23.5.7 Unreachable sentinel [unreachable.sentinel]

Class unreachable_­sentinel_­t can be used with any weakly_­incrementable type to denote the “upper bound” of an unbounded interval.

[Example 1: char* p;char* nl = find(p, unreachable_sentinel, '\n');

Provided a newline character really exists in the buffer, the use ofunreachable_­sentinel above potentially makes the call to find more efficient since the loop test against the sentinel does not require a conditional branch.

— _end example_]

namespace std { struct unreachable_sentinel_t { template<weakly_­incrementable I> friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept { return false; } };}

23.6 Stream iterators [stream.iterators]

23.6.1 General [stream.iterators.general]

To make it possible for algorithmic templates to work directly with input/output streams, appropriate iterator-like class templates are provided.

[Example 1:

partial_sum(istream_iterator<double, char>(cin), istream_iterator<double, char>(), ostream_iterator<double, char>(cout, "\n"));reads a file containing floating-point numbers fromcin, and prints the partial sums ontocout.

— _end example_]

23.6.2 Class template istream_­iterator [istream.iterator]

23.6.2.1 General [istream.iterator.general]

The class template istream_­iteratoris an input iterator ([input.iterators]) that reads successive elements from the input stream for which it was constructed.

namespace std { template<class T, class charT = char, class traits = char_traits<charT>,class Distance = ptrdiff_t> class istream_iterator { public: using iterator_category = input_iterator_tag;using value_type = T;using difference_type = Distance;using pointer = const T*;using reference = const T&;using char_type = charT;using traits_type = traits;using istream_type = basic_istream<charT,traits>;constexpr istream_iterator();constexpr istream_iterator(default_sentinel_t); istream_iterator(istream_type& s); istream_iterator(const istream_iterator& x) = default;~istream_iterator() = default; istream_iterator& operator=(const istream_iterator&) = default;const T& operator*() const;const T* operator->() const; istream_iterator& operator++(); istream_iterator operator++(int);friend bool operator==(const istream_iterator& i, default_sentinel_t);private: basic_istream<charT,traits>* in_stream; T value; };}

The type T shall meet the Cpp17DefaultConstructible,Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.

23.6.2.2 Constructors and destructor [istream.iterator.cons]

constexpr istream_iterator();constexpr istream_iterator(default_sentinel_t);

Effects: Constructs the end-of-stream iterator, value-initializing value.

Postconditions: in_­stream == nullptr is true.

Remarks: If the initializer T() in the declaration auto x = T();is a constant initializer ([expr.const]), then these constructors are constexpr constructors.

istream_iterator(istream_type& s);

Effects: Initializes in_­stream with addressof(s), value-initializes value, and then calls operator++().

istream_iterator(const istream_iterator& x) = default;

Postconditions: in_­stream == x.in_­stream is true.

Remarks: If is_­trivially_­copy_­constructible_­v<T> is true, then this constructor is trivial.

~istream_iterator() = default;

Remarks: If is_­trivially_­destructible_­v<T> is true, then this destructor is trivial.

23.6.2.3 Operations [istream.iterator.ops]

const T& operator*() const;

Preconditions: in_­stream != nullptr is true.

const T* operator->() const;

Preconditions: in_­stream != nullptr is true.

Returns: addressof(value).

istream_iterator& operator++();

Preconditions: in_­stream != nullptr is true.

Effects: Equivalent to:if (!(*in_stream >> value)) in_stream = nullptr;

istream_iterator operator++(int);

Preconditions: in_­stream != nullptr is true.

Effects: Equivalent to:istream_iterator tmp = *this;++*this;return tmp;

template<class T, class charT, class traits, class Distance> bool operator==(const istream_iterator<T,charT,traits,Distance>& x,const istream_iterator<T,charT,traits,Distance>& y);

Returns: x.in_­stream == y.in_­stream.

friend bool operator==(const istream_iterator& i, default_sentinel_t);

23.6.3 Class template ostream_­iterator [ostream.iterator]

23.6.3.1 General [ostream.iterator.general]

ostream_­iteratorwrites (usingoperator<<) successive elements onto the output stream from which it was constructed.

If it was constructed withcharT*as a constructor argument, this string, called adelimiter string, is written to the stream after everyTis written.

namespace std { template<class T, class charT = char, class traits = char_traits<charT>> class ostream_iterator { public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using char_type = charT;using traits_type = traits;using ostream_type = basic_ostream<charT,traits>;constexpr ostream_iterator() noexcept = default; ostream_iterator(ostream_type& s); ostream_iterator(ostream_type& s, const charT* delimiter); ostream_iterator(const ostream_iterator& x);~ostream_iterator(); ostream_iterator& operator=(const ostream_iterator&) = default; ostream_iterator& operator=(const T& value); ostream_iterator& operator*(); ostream_iterator& operator++(); ostream_iterator& operator++(int);private: basic_ostream<charT,traits>* out_stream = nullptr; const charT* delim = nullptr; };}

23.6.3.2 Constructors and destructor [ostream.iterator.cons.des]

ostream_iterator(ostream_type& s);

Effects: Initializes out_­stream with addressof(s) anddelim with nullptr.

ostream_iterator(ostream_type& s, const charT* delimiter);

Effects: Initializes out_­stream with addressof(s) anddelim with delimiter.

23.6.3.3 Operations [ostream.iterator.ops]

ostream_iterator& operator=(const T& value);

Effects: As if by:*out_stream << value;if (delim) *out_stream << delim;return *this;

ostream_iterator& operator*();

ostream_iterator& operator++(); ostream_iterator& operator++(int);

23.6.4 Class template istreambuf_­iterator [istreambuf.iterator]

23.6.4.1 General [istreambuf.iterator.general]

The class templateistreambuf_­iteratordefines an input iterator that reads successive_characters_from the streambuf for which it was constructed.

operator*provides access to the current input character, if any.

Each timeoperator++is evaluated, the iterator advances to the next input character.

If the end of stream is reached (streambuf_­type​::​sgetc() returnstraits​::​eof()), the iterator becomes equal to theend-of-streamiterator value.

The default constructoristreambuf_­iterator()and the constructoristreambuf_­iterator(nullptr)both construct an end-of-stream iterator object suitable for use as an end-of-range.

All specializations of istreambuf_­iterator shall have a trivial copy constructor, a constexpr default constructor, and a trivial destructor.

The result ofoperator*()on an end-of-stream iterator is undefined.

For any other iterator value achar_­typevalue is returned.

It is impossible to assign a character via an input iterator.

namespace std { template<class charT, class traits = char_traits<charT>> class istreambuf_iterator { public: using iterator_category = input_iterator_tag;using value_type = charT;using difference_type = typename traits::off_type;using pointer = unspecified;using reference = charT;using char_type = charT;using traits_type = traits;using int_type = typename traits::int_type;using streambuf_type = basic_streambuf<charT,traits>;using istream_type = basic_istream<charT,traits>;class proxy; constexpr istreambuf_iterator() noexcept;constexpr istreambuf_iterator(default_sentinel_t) noexcept; istreambuf_iterator(const istreambuf_iterator&) noexcept = default;~istreambuf_iterator() = default; istreambuf_iterator(istream_type& s) noexcept; istreambuf_iterator(streambuf_type* s) noexcept; istreambuf_iterator(const proxy& p) noexcept; istreambuf_iterator& operator=(const istreambuf_iterator&) noexcept = default; charT operator*() const; istreambuf_iterator& operator++();proxy operator++(int);bool equal(const istreambuf_iterator& b) const;friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s);private: streambuf_type* sbuf_; };}

23.6.4.2 Class istreambuf_­iterator​::​proxy [istreambuf.iterator.proxy]

Classistreambuf_­iterator<charT,traits>​::​_proxy_is for exposition only.

An implementation is permitted to provide equivalent functionality without providing a class with this name.

Classistreambuf_­iterator<charT, traits>​::​_proxy_provides a temporary placeholder as the return value of the post-increment operator (operator++).

It keeps the character pointed to by the previous value of the iterator for some possible future access to get the character.

namespace std { template<class charT, class traits> class istreambuf_iterator<charT, traits>::proxy { charT keep_; basic_streambuf<charT,traits>* sbuf_;proxy(charT c, basic_streambuf<charT,traits>* sbuf) : keep_(c), sbuf_(sbuf) { } public: charT operator*() { return keep_; } };}

23.6.4.3 Constructors [istreambuf.iterator.cons]

For each istreambuf_­iterator constructor in this subclause, an end-of-stream iterator is constructed if and only if the exposition-only member sbuf_­ is initialized with a null pointer value.

constexpr istreambuf_iterator() noexcept;constexpr istreambuf_iterator(default_sentinel_t) noexcept;

Effects: Initializes sbuf_­ with nullptr.

istreambuf_iterator(istream_type& s) noexcept;

Effects: Initializes sbuf_­ with s.rdbuf().

istreambuf_iterator(streambuf_type* s) noexcept;

Effects: Initializes sbuf_­ with s.

istreambuf_iterator(const _proxy_& p) noexcept;

Effects: Initializes sbuf_­ with p.sbuf_­.

23.6.4.4 Operations [istreambuf.iterator.ops]

Returns: The character obtained via thestreambufmembersbuf_­->sgetc().

istreambuf_iterator& operator++();

Effects: As if by sbuf_­->sbumpc().

Returns: proxy(sbuf_­->sbumpc(), sbuf_­).

bool equal(const istreambuf_iterator& b) const;

Returns: trueif and only if both iterators are at end-of-stream, or neither is at end-of-stream, regardless of whatstreambufobject they use.

template<class charT, class traits> bool operator==(const istreambuf_iterator<charT,traits>& a,const istreambuf_iterator<charT,traits>& b);

friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s);

23.6.5 Class template ostreambuf_­iterator [ostreambuf.iterator]

23.6.5.1 General [ostreambuf.iterator.general]

The class template ostreambuf_­iteratorwrites successive characters onto the output stream from which it was constructed.

namespace std { template<class charT, class traits = char_traits<charT>> class ostreambuf_iterator { public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using char_type = charT;using traits_type = traits;using streambuf_type = basic_streambuf<charT,traits>;using ostream_type = basic_ostream<charT,traits>;constexpr ostreambuf_iterator() noexcept = default; ostreambuf_iterator(ostream_type& s) noexcept; ostreambuf_iterator(streambuf_type* s) noexcept; ostreambuf_iterator& operator=(charT c); ostreambuf_iterator& operator*(); ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int);bool failed() const noexcept;private: streambuf_type* sbuf_ = nullptr; };}

23.6.5.2 Constructors [ostreambuf.iter.cons]

ostreambuf_iterator(ostream_type& s) noexcept;

Preconditions: s.rdbuf()is not a null pointer.

Effects: Initializes sbuf_­ with s.rdbuf().

ostreambuf_iterator(streambuf_type* s) noexcept;

Preconditions: sis not a null pointer.

Effects: Initializes sbuf_­ with s.

23.6.5.3 Operations [ostreambuf.iter.ops]

ostreambuf_iterator& operator=(charT c);

Effects: Iffailed()yieldsfalse, callssbuf_­->sputc(c); otherwise has no effect.

ostreambuf_iterator& operator*();

ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int);

bool failed() const noexcept;

Returns: trueif in any prior use of memberoperator=, the call tosbuf_­->sputc()returnedtraits​::​eof(); orfalseotherwise.

23.7 Range access [iterator.range]

In addition to being available via inclusion of the header, the function templates in [iterator.range] are available when any of the following headers are included:,,,,,,,,,,,, and.

Each of these templates is a designated customization point ([namespace.std]).

template<class C> constexpr auto begin(C& c) -> decltype(c.begin());template<class C> constexpr auto begin(const C& c) -> decltype(c.begin());

template<class C> constexpr auto end(C& c) -> decltype(c.end());template<class C> constexpr auto end(const C& c) -> decltype(c.end());

template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;

template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;

template<class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c));

Returns: std​::​begin(c).

template<class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c));

template<class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin());template<class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());

template<class C> constexpr auto rend(C& c) -> decltype(c.rend());template<class C> constexpr auto rend(const C& c) -> decltype(c.rend());

template<class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]);

Returns: reverse_­iterator<T*>(array + N).

template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]);

Returns: reverse_­iterator<T*>(array).

template<class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);

Returns: reverse_­iterator<const E*>(il.end()).

template<class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il);

Returns: reverse_­iterator<const E*>(il.begin()).

template<class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));

Returns: std​::​rbegin(c).

template<class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));

template<class C> constexpr auto size(const C& c) -> decltype(c.size());

template<class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept;

template<class C> constexpr auto ssize(const C& c) -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;

Effects: Equivalent to:return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size());

template<class T, ptrdiff_t N> constexpr ptrdiff_t ssize(const T (&array)[N]) noexcept;

template<class C> [[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty());

template<class T, size_t N> [[nodiscard]] constexpr bool empty(const T (&array)[N]) noexcept;

template<class E> [[nodiscard]] constexpr bool empty(initializer_list<E> il) noexcept;

template<class C> constexpr auto data(C& c) -> decltype(c.data());template<class C> constexpr auto data(const C& c) -> decltype(c.data());

template<class T, size_t N> constexpr T* data(T (&array)[N]) noexcept;

template<class E> constexpr const E* data(initializer_list<E> il) noexcept;