22 Iterators library [iterators]

22.3 Iterator requirements [iterator.requirements]

22.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 iterator i supports the expression *i, resulting in a value of some object type T, called the value type of the iterator.
An output iterator i has a non-empty set of types that are writable to the iterator; for each such type T, the expression *i = o is valid where o is a value of type T.
For every iterator type X, there is a corresponding signed integer type called the difference type of 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, and contiguous iterators, as shown in Table 72.
Table 72 — Relations among iterator categories
Contiguous
Random Access
Bidirectional
Forward
Input
Output
The six categories of iterators correspond to the iterator concepts InputIterator ([iterator.concept.input]), OutputIterator ([iterator.concept.output]), ForwardIterator ([iterator.concept.forward]), BidirectionalIterator ([iterator.concept.bidir]) RandomAccessIterator ([iterator.concept.random.access]), and ContiguousIterator ([iterator.concept.contiguous]), respectively.
The generic term iterator refers to any type that models the Iterator concept ([iterator.concept.iterator]).
Forward iterators satisfy all the requirements of input iterators and can be used whenever an input iterator is specified; Bidirectional iterators also satisfy all the requirements of forward iterators and can be used whenever a forward iterator is specified; Random access iterators also satisfy all the requirements of bidirectional iterators and can be used whenever a bidirectional iterator is specified; Contiguous iterators also satisfy all the requirements of random access iterators and can be used whenever a random access iterator is specified.
Iterators that further satisfy 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
:
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.
These values are called past-the-end values.
Values of an iterator i for 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.
[Example
:
After the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer.
end example
]
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 satisfy the Cpp17DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move operation.
[Note
:
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 sentinel that 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.231
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 by i and 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 [i, n) is empty if n == 0; otherwise, [i, n) 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 [i, n) is valid if and only if n == 0; or n is positive, i is dereferenceable, and [++i, --n) 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 iterator is an iterator that may be singular.232
Iterators are called constexpr iterators if all operations provided to meet iterator category requirements are constexpr functions, except for
[Note
:
For example, the types “pointer to int” and reverse_­iterator<int*> are constexpr iterators.
end note
]
The sentinel denoting the end of a range may have the same type as the iterator denoting the beginning of the range, or a different type.
This definition applies to pointers, since pointers are iterators.
The effect of dereferencing an iterator that has been invalidated is undefined.

22.3.2 Associated types [iterator.assoc.types]

22.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 the WeaklyIncrementable concept ([iterator.concept.winc]), the type
iter_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;
}
The type iter_­difference_­t<I> denotes
  • incrementable_­traits<I>::difference_­type if iterator_­traits<I> names a specialization generated from the primary template, and
  • iterator_­traits<I>::​difference_­type otherwise.
Users may specialize incrementable_­traits on program-defined types.

22.3.2.2 Readable traits [readable.traits]

To implement algorithms only in terms of readable types, it is often necessary to determine the value type that corresponds to a particular readable type.
Accordingly, it is required that if R is the name of a type that models the Readable concept ([iterator.concept.readable]), the type
iter_value_t<R>
be defined as the readable type's value type.
  template<class> struct cond-value-type { };   // exposition only
  template<class T>
    requires is_object_v<T>
  struct cond-value-type {
    using value_type = remove_cv_t<T>;
  };

  template<class> struct readable_traits { };

  template<class T>
  struct readable_traits<T*>
    : cond-value-type<T> { };

  template<class I>
    requires is_array_v<I>
  struct readable_traits<I> {
    using value_type = remove_cv_t<remove_extent_t<I>>;
  };

  template<class I>
  struct readable_traits<const I>
    : readable_traits<I> { };

  template<class T>
    requires requires { typename T::value_type; }
  struct readable_traits<T>
    : cond-value-type<typename T::value_type> { };

  template<class T>
    requires requires { typename T::element_type; }
  struct readable_traits<T>
    : cond-value-type<typename T::element_type> { };

  template<class T> using iter_value_t = see below;
The type iter_­value_­t<I> denotes
  • readable_­traits<I>::value_­type if iterator_­traits<I> names a specialization generated from the primary template, and
  • iterator_­traits<I>::value_­type otherwise.
Class template readable_­traits may be specialized on program-defined types.
[Note
:
Some legacy output iterators define a nested type named value_­type that is an alias for void.
These types are not Readable and have no associated value types.
end note
]
[Note
:
Smart pointers like shared_­ptr<int> are Readable and have an associated value type, but a smart pointer like shared_­ptr<void> is not Readable and has no associated value type.
end note
]

22.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 if I is the type of an iterator, the type
iterator_traits<I>::iterator_category
be defined as the iterator's iterator category.
In addition, the types
iterator_traits<I>::pointer
iterator_traits<I>::reference
shall be defined as the iterator's pointer and reference types; that is, for an iterator object a of class type, the same type as decltype(a.operator->()) and decltype(*a), respectively.
The type iterator_­traits<I>::pointer shall be void for an iterator of class type I that does not support operator->.
Additionally, in the case of an output iterator, the types
iterator_traits<I>::value_type
iterator_traits<I>::difference_type
iterator_traits<I>::reference
may 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<I&>;
    { *i++ } -> can-reference;
  };

template<class I>
concept cpp17-input-iterator =
  cpp17-iterator<I> && EqualityComparable<I> && requires(I i) {
    typename incrementable_traits<I>::difference_type;
    typename readable_traits<I>::value_type;
    typename common_reference_t<iter_reference_t<I>&&,
                                typename readable_traits<I>::value_type&>;
    *i++;
    typename common_reference_t<decltype(*i++)&&,
                                typename readable_traits<I>::value_type&>;
    requires SignedIntegral<typename incrementable_traits<I>::difference_type>;
  };

template<class I>
concept cpp17-forward-iterator =
  cpp17-input-iterator<I> && Constructible<I> &&
  is_lvalue_reference_v<iter_reference_t<I>> &&
  Same<remove_cvref_t<iter_reference_t<I>>, typename readable_traits<I>::value_type> &&
  requires(I i) {
    {  i++ } -> const I&;
    { *i++ } -> Same<iter_reference_t<I>>;
  };

template<class I>
concept cpp17-bidirectional-iterator =
  cpp17-forward-iterator<I> && requires(I i) {
    {  --i } -> Same<I&>;
    {  i-- } -> const I&;
    { *i-- } -> Same<iter_reference_t<I>>;
  };

template<class I>
concept cpp17-random-access-iterator =
  cpp17-bidirectional-iterator<I> && StrictTotallyOrdered<I> &&
  requires(I i, typename incrementable_traits<I>::difference_type n) {
    { i += n } -> Same<I&>;
    { i -= n } -> Same<I&>;
    { i +  n } -> Same<I>;
    { n +  i } -> Same<I>;
    { i -  n } -> Same<I>;
    { i -  i } -> Same<decltype(n)>;
    {  i[n]  } -> iter_reference_t<I>;
  };
The members of a specialization iterator_­traits<I> generated from the iterator_­traits primary template are computed as follows:
  • If I has valid ([temp.deduct]) member types difference_­type, value_­type, reference, and iterator_­category, then iterator_­traits<I> has the following publicly accessible members:
      using iterator_category = typename I::iterator_category;
      using value_type        = typename I::value_type;
      using difference_type   = typename I::difference_type;
      using pointer           = see below;
      using reference         = typename I::reference;
    
    If the qualified-id I::pointer is valid and denotes a type, then iterator_­traits<I>::pointer names that type; otherwise, it names void.
  • Otherwise, if I satisfies the exposition-only concept cpp17-input-iterator, iterator_­traits<I> has the following publicly accessible members:
      using iterator_category = see below;
      using value_type        = typename readable_traits<I>::value_type;
      using difference_type   = typename incrementable_traits<I>::difference_type;
      using pointer           = see below;
      using reference         = see below;
    
    • If the qualified-id I::pointer is valid and denotes a type, pointer names that type.
      Otherwise, if decltype(​declval<I&>().operator->()) is well-formed, then pointer names that type.
      Otherwise, pointer names void.
    • If the qualified-id I::reference is valid and denotes a type, reference names that type.
      Otherwise, reference names iter_­reference_­t<I>.
    • If the qualified-id I::iterator_­category is valid and denotes a type, iterator_­category names that type.
      Otherwise, iterator_­category names:
      • random_­access_­iterator_­tag if I satisfies cpp17-random-access-iterator, or otherwise
      • bidirectional_­iterator_­tag if I satisfies cpp17-bidirectional-iterator, or otherwise
      • forward_­iterator_­tag if I satisfies cpp17-forward-iterator, or otherwise
      • input_­iterator_­tag.
  • Otherwise, if I satisfies the exposition-only concept cpp17-iterator, then iterator_­traits<I> has the following publicly accessible members:
      using iterator_category = output_iterator_tag;
      using value_type        = void;
      using difference_type   = see below;
      using pointer           = void;
      using reference         = void;
    
    If the qualified-id incrementable_­traits<I>::difference_­type is valid and denotes a type, then difference_­type names that type; otherwise, it names void.
  • Otherwise, iterator_­traits<I> has no members by any of the above names.
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 as
namespace 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
:
To implement a generic reverse function, 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
]

22.3.3 Customization points [iterator.cust]

22.3.3.1 iter_­move [iterator.cust.move]

The name iter_­move denotes a customization point object ([customization.point.object]).
The expression ranges::iter_­move(E) for some subexpression E is expression-equivalent to the following:
  • iter_­move(E), if that expression is valid, with overload resolution performed in a context that does not include a declaration of ranges::iter_­move.
  • Otherwise, if the expression *E is well-formed:
  • Otherwise, ranges::iter_­move(E) is ill-formed.
    [Note
    :
    This case can result in substitution failure when ranges::iter_­move(E) appears in the immediate context of a template instantiation.
    end note
    ]
If ranges::iter_­move(E) is not equal to *E, the program is ill-formed with no diagnostic required.

22.3.3.2 iter_­swap [iterator.cust.swap]

The name iter_­swap denotes a customization point object ([customization.point.object]) that exchanges the values ([concept.swappable]) denoted by its arguments.
Let iter-exchange-move be the exposition-only function:
template<class X, class Y> constexpr iter_value_t<remove_reference_t<X>> iter-exchange-move(X&& x, Y&& y) noexcept(noexcept(iter_value_t<remove_reference_t<X>>(iter_move(x))) && noexcept(*x = iter_move(y)));
Effects: Equivalent to:
iter_value_t<remove_reference_t<X>> old_value(iter_move(x));
*x = iter_move(y);
return old_value;
The expression ranges::iter_­swap(E1, E2) for some subexpressions E1 and E2 is expression-equivalent to the following:
  • (void)iter_­swap(E1, E2), if that expression is valid, with overload resolution performed in a context that includes the declaration
    template<class I1, class I2>
      void iter_swap(I1, I2) = delete;
    
    and does not include a declaration of ranges::iter_­swap.
    If the function selected by overload resolution does not exchange the values denoted by E1 and E2, the program is ill-formed with no diagnostic required.
  • Otherwise, if the types of E1 and E2 each model Readable, and if the reference types of E1 and E2 model SwappableWith ([concept.swappable]), then ranges::swap(*E1, *E2).
  • Otherwise, if the types T1 and T2 of E1 and E2 model IndirectlyMovableStorable<T1, T2> and IndirectlyMovableStorable<T2, T1>, then (void)(*E1 = iter-exchange-move(E2, E1)), except that E1 is evaluated only once.
  • Otherwise, ranges::iter_­swap(E1, E2) is ill-formed.
    [Note
    :
    This case can result in substitution failure when ranges::iter_­swap(E1, E2) appears in the immediate context of a template instantiation.
    end note
    ]

22.3.4 Iterator concepts [iterator.concepts]

22.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) denotes iterator_­traits<I>.
  • If the qualified-id ITER_­TRAITS(I)::iterator_­concept is valid and names a type, then ITER_­CONCEPT(I) denotes that type.
  • Otherwise, if the qualified-id ITER_­TRAITS(I)::iterator_­category is valid and names a type, then ITER_­CONCEPT(I) denotes that type.
  • Otherwise, if iterator_­traits<I> names a specialization generated from the primary template, then ITER_­CONCEPT(I) denotes random_­access_­iterator_­tag.
  • Otherwise, ITER_­CONCEPT(I) does not denote a type.
[Note
:
ITER_­TRAITS enables independent syntactic determination of an iterator's category and concept.
end note
]
[Example
:
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;
  bool operator!=(I) const;
};
iterator_­traits<I>::iterator_­category denotes input_­iterator_­tag, and ITER_­CONCEPT(I) denotes random_­access_­iterator_­tag.
end example
]

22.3.4.2 Concept Readable [iterator.concept.readable]

Types that are readable by applying operator* model the Readable concept, including pointers, smart pointers, and iterators.
template<class In>
  concept Readable =
    requires {
      typename iter_value_t<In>;
      typename iter_reference_t<In>;
      typename iter_rvalue_reference_t<In>;
    } &&
    CommonReference<iter_reference_t<In>&&, iter_value_t<In>&> &&
    CommonReference<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&&> &&
    CommonReference<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>;
Given a value i of type I, I models Readable only if the expression *i is equality-preserving.
[Note
:
The expression *i is indirectly required to be valid via the exposition-only dereferenceable concept ([iterator.synopsis]).
end note
]

22.3.4.3 Concept Writable [iterator.concept.writable]

The Writable concept specifies the requirements for writing a value into an iterator's referenced object.
template<class Out, class T>
  concept Writable =
    requires(Out&& o, T&& t) {
      *o = std::forward<T>(t); // not required to be equality-preserving
      *std::forward<Out>(o) = std::forward<T>(t); // not required to be equality-preserving
      const_cast<const iter_reference_t<Out>&&>(*o) =
        std::forward<T>(t); // not required to be equality-preserving
      const_cast<const iter_reference_t<Out>&&>(*std::forward<Out>(o)) =
        std::forward<T>(t); // not required to be equality-preserving
    };
Let E be an an expression such that decltype((E)) is T, and let o be a dereferenceable object of type Out.
Out and T model Writable<Out, T> only if
  • If Out and T model Readable<Out> && Same<iter_­value_­t<Out>, decay_­t<T>>, then *o after any above assignment is equal to the value of E before the assignment.
After evaluating any above assignment expression, o is not required to be dereferenceable.
If E is an xvalue ([basic.lval]), the resulting state of the object it denotes is valid but unspecified ([lib.types.movedfrom]).
[Note
:
The only valid use of an operator* is on the left side of the assignment statement.
Assignment through the same value of the writable type happens only once.
end note
]
[Note
:
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::string by value does not model Writable<I, std::string>.
end note
]

22.3.4.4 Concept WeaklyIncrementable [iterator.concept.winc]

The WeaklyIncrementable 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 EqualityComparable.
template<class I>
  concept WeaklyIncrementable =
    Semiregular<I> &&
    requires(I i) {
      typename iter_difference_t<I>;
      requires SignedIntegral<iter_difference_t<I>>;
      { ++i } -> Same<I&>; // not required to be equality-preserving
      i++; // not required to be equality-preserving
    };
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 WeaklyIncrementable<I> only if
  • The expressions ++i and i++ have the same domain.
  • If i is incrementable, then both ++i and i++ advance i to the next element.
  • If i is incrementable, then addressof(++i) is equal to addressof(i).
[Note
:
For WeaklyIncrementable types, a equals b does not imply that ++a equals ++b.
(Equality does not guarantee the substitution property or referential transparency.)
Algorithms on weakly incrementable types should never attempt to pass through the same incrementable value twice.
They should be single-pass algorithms.
These algorithms can be used with istreams as the source of the input data through the istream_­iterator class template.
end note
]

22.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 EqualityComparable.
[Note
:
This supersedes the annotations on the increment expressions in the definition of WeaklyIncrementable.
end note
]
template<class I>
  concept Incrementable =
    Regular<I> &&
    WeaklyIncrementable<I> &&
    requires(I i) {
      { i++ } -> Same<I>;
    };
Let a and b be incrementable objects of type I.
I models Incrementable only if
  • If bool(a == b) then bool(a++ == b).
  • If bool(a == b) then bool(((void)a++, a) == ++b).
[Note
:
The requirement that a equals b implies ++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
]

22.3.4.6 Concept Iterator [iterator.concept.iterator]

The Iterator concept forms the basis of the iterator concept taxonomy; every iterator models 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 Iterator =
    requires(I i) {
      { *i } -> can-reference;
    } &&
    WeaklyIncrementable<I>;

22.3.4.7 Concept Sentinel [iterator.concept.sentinel]

The Sentinel concept specifies the relationship between an Iterator type and a Semiregular type whose values denote a range.
template<class S, class I> concept Sentinel = Semiregular<S> && Iterator<I> && weakly-equality-comparable-with<S, I>; // See [concept.equalitycomparable]
Let s and i be values of type S and I such that [i, s) denotes a range.
Types S and I model Sentinel<S, I> only if
  • i == s is well-defined.
  • If bool(i != s) then i is dereferenceable and [++i, s) denotes a range.
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.

22.3.4.8 Concept SizedSentinel [iterator.concept.sizedsentinel]

The SizedSentinel concept specifies requirements on an Iterator and a Sentinel that allow the use of the - operator to compute the distance between them in constant time.
template<class S, class I> concept SizedSentinel = Sentinel<S, I> && !disable_sized_sentinel<remove_cv_t<S>, remove_cv_t<I>> && requires(const I& i, const S& s) { { s - i } -> Same<iter_difference_t<I>>; { i - s } -> Same<iter_difference_t<I>>; };
Let i be an iterator of type I, and s a sentinel of type S such that [i, s) denotes a range.
Let N be the smallest number of applications of ++i necessary to make bool(i == s) be true.
S and I model SizedSentinel<S, I> only if
  • If N is representable by iter_­difference_­t<I>, then s - i is well-defined and equals N.
  • If is representable by iter_­difference_­t<I>, then i - s is well-defined and equals .
[Note
:
disable_­sized_­sentinel allows use of sentinels and iterators with the library that satisfy but do not in fact model SizedSentinel.
end note
]
[Example
:
The SizedSentinel concept is modeled by pairs of RandomAccessIterators ([iterator.concept.random.access]) and by counted iterators and their sentinels ([counted.iterator]).
end example
]

22.3.4.9 Concept InputIterator [iterator.concept.input]

The InputIterator concept defines requirements for a type whose referenced values can be read (from the requirement for Readable ([iterator.concept.readable])) and which can be both pre- and post-incremented.
[Note
:
Unlike the Cpp17InputIterator requirements ([input.iterators]), the InputIterator concept does not need equality comparison since iterators are typically compared to sentinels.
end note
]
template<class I>
  concept InputIterator =
    Iterator<I> &&
    Readable<I> &&
    requires { typename ITER_CONCEPT(I); } &&
    DerivedFrom<ITER_CONCEPT(I), input_iterator_tag>;

22.3.4.10 Concept OutputIterator [iterator.concept.output]

The OutputIterator concept defines requirements for a type that can be used to write values (from the requirement for Writable ([iterator.concept.writable])) and which can be both pre- and post-incremented.
[Note
:
Output iterators are not required to model EqualityComparable.
end note
]
template<class I, class T>
  concept OutputIterator =
    Iterator<I> &&
    Writable<I, T> &&
    requires(I i, T&& t) {
      *i++ = std::forward<T>(t); // not required to be equality-preserving
    };
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 OutputIterator<I, T> only if *i++ = E; has effects equivalent to:
  *i = E;
  ++i;
[Note
:
Algorithms on output iterators should never attempt to pass through the same iterator twice.
They should be single-pass algorithms.
end note
]

22.3.4.11 Concept ForwardIterator [iterator.concept.forward]

The ForwardIterator concept adds equality comparison and the multi-pass guarantee, specified below.
template<class I>
  concept ForwardIterator =
    InputIterator<I> &&
    DerivedFrom<ITER_CONCEPT(I), forward_iterator_tag> &&
    Incrementable<I> &&
    Sentinel<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
:
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 X offer the multi-pass guarantee if:
  • a == b implies ++a == ++b and
  • The expression ((void)[](X x){++x;}(a), *a) is equivalent to the expression *a.
[Note
:
The requirement that a == b implies ++a == ++b and 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
]

22.3.4.12 Concept BidirectionalIterator [iterator.concept.bidir]

The BidirectionalIterator concept adds the ability to move an iterator backward as well as forward.
template<class I>
  concept BidirectionalIterator =
    ForwardIterator<I> &&
    DerivedFrom<ITER_CONCEPT(I), bidirectional_iterator_tag> &&
    requires(I i) {
      { --i } -> Same<I&>;
      { i-- } -> Same<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 BidirectionalIterator only if:
  • If a and b are decrementable, then all of the following are true:
    • addressof(--a) == addressof(a)
    • bool(a-- == b)
    • after evaluating both a-- and --b, bool(a == b) is still true
    • bool(++(--a) == b)
  • If a and b are incrementable, then bool(--(++a) == b).

22.3.4.13 Concept RandomAccessIterator [iterator.concept.random.access]

The RandomAccessIterator 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 RandomAccessIterator =
    BidirectionalIterator<I> &&
    DerivedFrom<ITER_CONCEPT(I), random_access_iterator_tag> &&
    StrictTotallyOrdered<I> &&
    SizedSentinel<I, I> &&
    requires(I i, const I j, const iter_difference_t<I> n) {
      { i += n } -> Same<I&>;
      { j +  n } -> Same<I>;
      { n +  j } -> Same<I>;
      { i -= n } -> Same<I&>;
      { j -  n } -> Same<I>;
      {  j[n]  } -> Same<iter_reference_t<I>>;
    };
Let a and b be valid iterators of type I such that b is reachable from a after n applications of ++a, let D be iter_­difference_­t<I>, and let n denote a value of type D.
I models RandomAccessIterator only if
  • (a += n) is equal to b.
  • addressof(a += n) is equal to addressof(a).
  • (a + n) is equal to (a += n).
  • For any two positive values x and y of type D, if (a + D(x + y)) is valid, then (a + D(x + y)) is equal to ((a + x) + y).
  • (a + D(0)) is equal to a.
  • If (a + D(n - 1)) is valid, then (a + n) is equal to ++(a + D(n - 1)).
  • (b += -n) is equal to a.
  • (b -= n) is equal to a.
  • addressof(b -= n) is equal to addressof(b).
  • (b - n) is equal to (b -= n).
  • If b is dereferenceable, then a[n] is valid and is equal to *b.
  • bool(a <= b) is true.

22.3.4.14 Concept ContiguousIterator [iterator.concept.contiguous]

The ContiguousIterator concept provides a guarantee that the denoted elements are stored contiguously in memory.
template<class I>
  concept ContiguousIterator =
    RandomAccessIterator<I> &&
    DerivedFrom<ITER_CONCEPT(I), contiguous_iterator_tag> &&
    is_lvalue_reference_v<iter_reference_t<I>> &&
    Same<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>>;
Let a and b be dereferenceable iterators of type I such that b is reachable from a, and let D be iter_­difference_­t<I>.
The type I models ContiguousIterator only if addressof(*(a + D(b - a))) is equal to addressof(*a) + D(b - a).

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

In the following sections, a and b denote values of type X or const X, difference_­type and reference refer to the types iterator_­traits<X>::difference_­type and iterator_­traits<X>::reference, respectively, n denotes a value of difference_­type, u, tmp, and m denote identifiers, r denotes a value of X&, t denotes a value of value type T, o denotes a value of some type that is writable to the output iterator.
[Note
:
For an iterator type X there must be an instantiation of iterator_­traits<X> ([iterator.traits]).
end note
]

22.3.5.1 Cpp17Iterator [iterator.iterators]

The Cpp17Iterator requirements form the basis of the iterator taxonomy; every iterator satisfies 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 satisfies the Cpp17Iterator requirements if:
Table 73Cpp17Iterator requirements
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
*r
unspecified
Requires: r is dereferenceable.
++r
X&

22.3.5.2 Input iterators [input.iterators]

A class or pointer type X satisfies the requirements of an input iterator for the value type T if X satisfies the Cpp17Iterator ([iterator.iterators]) and Cpp17EqualityComparable (Table 23) requirements and the expressions in Table 74 are valid and have the indicated semantics.
In Table 74, the term the 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
:
The call find(a,b,x) is defined only if the value of a has the property p defined as follows: b has property p and a value i has property p if (*i==x) or if (*i!=x and ++i has property p).
end example
]
Table 74Cpp17InputIterator requirements (in addition to Cpp17Iterator)
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
a != b
contextually convertible to bool
!(a == b)
Requires: (a, b) is in the domain of ==.
*a
reference, convertible to T
Requires: 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
Requires: a is dereferenceable.
++r
X&
Requires: r is dereferenceable.

Ensures: 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; }
[Note
:
For input iterators, a == b does not imply ++a == ++b.
(Equality does not guarantee the substitution property or referential transparency.)
Algorithms on input iterators should never attempt to pass through the same iterator twice.
They should be single pass algorithms.
Value type T is not required to be a Cpp17CopyAssignable type (Table 29).
These algorithms can be used with istreams as the source of the input data through the istream_­iterator class template.
end note
]

22.3.5.3 Output iterators [output.iterators]

A class or pointer type X satisfies the requirements of an output iterator if X satisfies the Cpp17Iterator requirements ([iterator.iterators]) and the expressions in Table 75 are valid and have the indicated semantics.
Table 75Cpp17OutputIterator requirements (in addition to Cpp17Iterator)
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.

Ensures: r is incrementable.
++r
X&
addressof(r) == addressof(++r).

Remarks:  After this operation r is not required to be dereferenceable.

Ensures: 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.

Ensures: r is incrementable.
*r++ = o
result is not used
Remarks:  After this operation r is not required to be dereferenceable.

Ensures: r is incrementable.
[Note
:
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.
Algorithms on output iterators should never attempt to pass through the same iterator twice.
They should be single-pass algorithms.
Equality and inequality might not be defined.
end note
]

22.3.5.4 Forward iterators [forward.iterators]

A class or pointer type X satisfies the requirements of a forward iterator if
  • X satisfies the Cpp17InputIterator requirements ([input.iterators]),
  • X satisfies the Cpp17DefaultConstructible requirements ([utility.arg.requirements]),
  • if X is a mutable iterator, reference is a reference to T; if X is a constant iterator, reference is a reference to const T,
  • the expressions in Table 76 are valid and have the indicated semantics, and
  • objects of type X offer the multi-pass guarantee, described below.
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
:
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 the multi-pass guarantee if:
  • a == b implies ++a == ++b and
  • X is a pointer type or the expression (void)++X(a), *a is equivalent to the expression *a.
[Note
:
The requirement that a == b implies ++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 76Cpp17ForwardIterator requirements (in addition to Cpp17InputIterator)
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 b are both dereferenceable or else neither is dereferenceable.
If a and b are both dereferenceable, then a == b if and only if *a and *b are bound to the same object.

22.3.5.5 Bidirectional iterators [bidirectional.iterators]

A class or pointer type X satisfies the requirements of a bidirectional iterator if, in addition to satisfying the Cpp17ForwardIterator requirements, the following expressions are valid as shown in Table 77.
Table 77Cpp17BidirectionalIterator requirements (in addition to Cpp17ForwardIterator)
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
--r
X&
Requires: there exists s such that r == ++s.

Ensures: 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
:
Bidirectional iterators allow algorithms to move iterators backward as well as forward.
end note
]

22.3.5.6 Random access iterators [random.access.iterators]

A class or pointer type X satisfies the requirements of a random access iterator if, in addition to satisfying the Cpp17BidirectionalIterator requirements, the following expressions are valid as shown in Table 78.
Table 78Cpp17RandomAccessIterator requirements (in addition to Cpp17BidirectionalIterator)
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 + n
n + a
X
{ X tmp = a;
return tmp += n; }
a + n == n + a.
r -= n
X&
return r += -n;
Requires: 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
Requires: 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)

22.3.6 Indirect callable requirements [indirectcallable]

22.3.6.1 General [indirectcallable.general]

There are several concepts that group requirements of algorithms that take callable objects ([func.def]) as arguments.

22.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 IndirectUnaryInvocable =
      Readable<I> &&
      CopyConstructible<F> &&
      Invocable<F&, iter_value_t<I>&> &&
      Invocable<F&, iter_reference_t<I>> &&
      Invocable<F&, iter_common_reference_t<I>> &&
      CommonReference<
        invoke_result_t<F&, iter_value_t<I>&>,
        invoke_result_t<F&, iter_reference_t<I>>>;

  template<class F, class I>
    concept IndirectRegularUnaryInvocable =
      Readable<I> &&
      CopyConstructible<F> &&
      RegularInvocable<F&, iter_value_t<I>&> &&
      RegularInvocable<F&, iter_reference_t<I>> &&
      RegularInvocable<F&, iter_common_reference_t<I>> &&
      CommonReference<
        invoke_result_t<F&, iter_value_t<I>&>,
        invoke_result_t<F&, iter_reference_t<I>>>;

  template<class F, class I>
    concept IndirectUnaryPredicate =
      Readable<I> &&
      CopyConstructible<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 = I1>
    concept IndirectRelation =
      Readable<I1> && Readable<I2> &&
      CopyConstructible<F> &&
      Relation<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
      Relation<F&, iter_value_t<I1>&, iter_reference_t<I2>> &&
      Relation<F&, iter_reference_t<I1>, iter_value_t<I2>&> &&
      Relation<F&, iter_reference_t<I1>, iter_reference_t<I2>> &&
      Relation<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

  template<class F, class I1, class I2 = I1>
    concept IndirectStrictWeakOrder =
      Readable<I1> && Readable<I2> &&
      CopyConstructible<F> &&
      StrictWeakOrder<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
      StrictWeakOrder<F&, iter_value_t<I1>&, iter_reference_t<I2>> &&
      StrictWeakOrder<F&, iter_reference_t<I1>, iter_value_t<I2>&> &&
      StrictWeakOrder<F&, iter_reference_t<I1>, iter_reference_t<I2>> &&
      StrictWeakOrder<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;
}

22.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 Readable type I and a callable object type Proj into a new Readable type whose reference type is the result of applying Proj to the iter_­reference_­t of I.
namespace std {
  template<Readable I, IndirectRegularUnaryInvocable<I> Proj>
  struct projected {
    using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>;
    indirect_result_t<Proj&, I> operator*() const; // not defined
  };

  template<WeaklyIncrementable I, class Proj>
  struct incrementable_traits<projected<I, Proj>> {
    using difference_type = iter_difference_t<I>;
  };
}

22.3.7 Common algorithm requirements [alg.req]

22.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 between Readable and Writable types: IndirectlyMovable, IndirectlyCopyable, and IndirectlySwappable.
There are three relational concepts for rearrangements: Permutable, Mergeable, and Sortable.
There is one relational concept for comparing values from different sequences: IndirectlyComparable.
[Note
:
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
]

22.3.7.2 Concept IndirectlyMovable [alg.req.ind.move]

The IndirectlyMovable concept specifies the relationship between a Readable type and a Writable type between which values may be moved.
template<class In, class Out>
  concept IndirectlyMovable =
    Readable<In> &&
    Writable<Out, iter_rvalue_reference_t<In>>;
The IndirectlyMovableStorable concept augments IndirectlyMovable with additional requirements enabling the transfer to be performed through an intermediate object of the Readable type's value type.
template<class In, class Out>
  concept IndirectlyMovableStorable =
    IndirectlyMovable<In, Out> &&
    Writable<Out, iter_value_t<In>> &&
    Movable<iter_value_t<In>> &&
    Constructible<iter_value_t<In>, iter_rvalue_reference_t<In>> &&
    Assignable<iter_value_t<In>&, iter_rvalue_reference_t<In>>;
Let i be a dereferenceable value of type In.
In and Out model IndirectlyMovableStorable<In, Out> only if after the initialization of the object obj in
iter_value_t<In> obj(ranges::iter_move(i));
obj is equal to the value previously denoted by *i.
If iter_­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]).

22.3.7.3 Concept IndirectlyCopyable [alg.req.ind.copy]

The IndirectlyCopyable concept specifies the relationship between a Readable type and a Writable type between which values may be copied.
template<class In, class Out>
  concept IndirectlyCopyable =
    Readable<In> &&
    Writable<Out, iter_reference_t<In>>;
The IndirectlyCopyableStorable concept augments IndirectlyCopyable with additional requirements enabling the transfer to be performed through an intermediate object of the Readable type's value type.
It also requires the capability to make copies of values.
template<class In, class Out>
  concept IndirectlyCopyableStorable =
    IndirectlyCopyable<In, Out> &&
    Writable<Out, const iter_value_t<In>&> &&
    Copyable<iter_value_t<In>> &&
    Constructible<iter_value_t<In>, iter_reference_t<In>> &&
    Assignable<iter_value_t<In>&, iter_reference_t<In>>;
Let i be a dereferenceable value of type In.
In and Out model IndirectlyCopyableStorable<In, Out> only if after the initialization of the object obj in
iter_value_t<In> obj(*i);
obj is equal to the value previously denoted by *i.
If iter_­reference_­t<In> is an rvalue reference type, the resulting state of the value denoted by *i is valid but unspecified ([lib.types.movedfrom]).

22.3.7.4 Concept IndirectlySwappable [alg.req.ind.swap]

The IndirectlySwappable concept specifies a swappable relationship between the values referenced by two Readable types.
template<class I1, class I2 = I1>
  concept IndirectlySwappable =
    Readable<I1> && Readable<I2> &&
    requires(I1& i1, I2& i2) {
      ranges::iter_swap(i1, i1);
      ranges::iter_swap(i2, i2);
      ranges::iter_swap(i1, i2);
      ranges::iter_swap(i2, i1);
    };

22.3.7.5 Concept IndirectlyComparable [alg.req.ind.cmp]

The IndirectlyComparable 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 IndirectlyComparable =
    IndirectRelation<R, projected<I1, P1>, projected<I2, P2>>;

22.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 =
    ForwardIterator<I> &&
    IndirectlyMovableStorable<I, I> &&
    IndirectlySwappable<I, I>;

22.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 =
    InputIterator<I1> &&
    InputIterator<I2> &&
    WeaklyIncrementable<Out> &&
    IndirectlyCopyable<I1, Out> &&
    IndirectlyCopyable<I2, Out> &&
    IndirectStrictWeakOrder<R, projected<I1, P1>, projected<I2, P2>>;

22.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> &&
    IndirectStrictWeakOrder<R, projected<I, P>>;