9 Iterators library [iterators]

9.1 General [iterators.general]

This Clause describes components that C++ programs may use to perform iterations over containers (Clause ISO/IEC 14882:2014 §[containers]), streams ( ISO/IEC 14882:2014 §[iostream.format]), and stream buffers ( ISO/IEC 14882:2014 §[stream.buffers]).

The following subclauses describe iterator requirements, and components for iterator primitives, predefined iterators, and stream iterators, as summarized in Table [tab:iterators.lib.summary].

Table 7 — Iterators library summary
Subclause Header(s)
[iterator.requirements] Iterator requirements
[indirectcallable] Indirect callable requirements
[commonalgoreq] Common algorithm requirements
[iterator.primitives] Iterator primitives <experimental/ranges/iterator>
[iterators.predef] Predefined iterators
[iterators.stream] Stream iterators

9.2 Header <experimental/ranges/iterator> synopsis [iterator.synopsis]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class T> concept bool dereferenceable // exposition only
    = requires(T& t) { {*t} -> auto&&; };

  // [iterator.requirements], iterator requirements:
  // [iterator.custpoints], customization points:
  namespace {
    // [iterator.custpoints.iter_move], iter_move:
    constexpr unspecified iter_move = unspecified;

    // [iterator.custpoints.iter_swap], iter_swap:
    constexpr unspecified iter_swap = unspecified;
  }

  // [iterator.assoc.types], associated types:
  // [iterator.assoc.types.difference_type], difference_type:
  template <class> struct difference_type;
  template <class T> using difference_type_t
    = typename difference_type<T>::type;

  // [iterator.assoc.types.value_type], value_type:
  template <class> struct value_type;
  template <class T> using value_type_t
    = typename value_type<T>::type;

  // [iterator.assoc.types.iterator_category], iterator_category:
  template <class> struct iterator_category;
  template <class T> using iterator_category_t
    = typename iterator_category<T>::type;

  template <dereferenceable T> using reference_t
    = decltype(*declval<T&>());

  template <dereferenceable T>
      requires see below using rvalue_reference_t
    = decltype(ranges::iter_move(declval<T&>()));

  // [iterators.readable], Readable:
  template <class In>
  concept bool Readable = see below;

  // [iterators.writable], Writable:
  template <class Out, class T>
  concept bool Writable = see below;

  // [iterators.weaklyincrementable], WeaklyIncrementable:
  template <class I>
  concept bool WeaklyIncrementable = see below;

  // [iterators.incrementable], Incrementable:
  template <class I>
  concept bool Incrementable = see below;

  // [iterators.iterator], Iterator:
  template <class I>
  concept bool Iterator = see below;

  // [iterators.sentinel], Sentinel:
  template <class S, class I>
  concept bool Sentinel = see below;

  // [iterators.sizedsentinel], SizedSentinel:
  template <class S, class I>
    constexpr bool disable_sized_sentinel = false;

  template <class S, class I>
  concept bool SizedSentinel = see below;

  // [iterators.input], InputIterator:
  template <class I>
  concept bool InputIterator = see below;

  // [iterators.output], OutputIterator:
  template <class I>
  concept bool OutputIterator = see below;

  // [iterators.forward], ForwardIterator:
  template <class I>
  concept bool ForwardIterator = see below;

  // [iterators.bidirectional], BidirectionalIterator:
  template <class I>
  concept bool BidirectionalIterator = see below;

  // [iterators.random.access], RandomAccessIterator:
  template <class I>
  concept bool RandomAccessIterator = see below;

  // [indirectcallable], indirect callable requirements:
  // [indirectcallable.indirectinvocable], indirect callables:
  template <class F, class I>
  concept bool IndirectUnaryInvocable = see below;

  template <class F, class I>
  concept bool IndirectRegularUnaryInvocable = see below;

  template <class F, class I>
  concept bool IndirectUnaryPredicate = see below;

  template <class F, class I1, class I2 = I1>
  concept bool IndirectRelation = see below;

  template <class F, class I1, class I2 = I1>
  concept bool IndirectStrictWeakOrder = see below;

  template <class> struct indirect_result_of;

  template <class F, class... Is>
    requires Invocable<F, reference_t<Is>...>
  struct indirect_result_of<F(Is...)>;

  template <class F>
  using indirect_result_of_t
    = typename indirect_result_of<F>::type;

  // [projected], projected:
  template <Readable I, IndirectRegularUnaryInvocable<I> Proj>
  struct projected;

  template <WeaklyIncrementable I, class Proj>
  struct difference_type<projected<I, Proj>>;

  // [commonalgoreq], common algorithm requirements:
  // [commonalgoreq.indirectlymovable] IndirectlyMovable:
  template <class In, class Out>
  concept bool IndirectlyMovable = see below;

  template <class In, class Out>
  concept bool IndirectlyMovableStorable = see below;

  // [commonalgoreq.indirectlycopyable] IndirectlyCopyable:
  template <class In, class Out>
  concept bool IndirectlyCopyable = see below;

  template <class In, class Out>
  concept bool IndirectlyCopyableStorable = see below;

  // [commonalgoreq.indirectlyswappable] IndirectlySwappable:
  template <class I1, class I2 = I1>
  concept bool IndirectlySwappable = see below;

  // [commonalgoreq.indirectlycomparable] IndirectlyComparable:
  template <class I1, class I2, class R = equal_to<>, class P1 = identity,
      class P2 = identity>
  concept bool IndirectlyComparable = see below;

  // [commonalgoreq.permutable] Permutable:
  template <class I>
  concept bool Permutable = see below;

  // [commonalgoreq.mergeable] Mergeable:
  template <class I1, class I2, class Out,
      class R = less<>, class P1 = identity, class P2 = identity>
  concept bool Mergeable = see below;

  template <class I, class R = less<>, class P = identity>
  concept bool Sortable = see below;

  // [iterator.primitives], primitives:
  // [iterator.traits], traits:
  template <class Iterator> using iterator_traits = see below;

  template <Readable T> using iter_common_reference_t
    = common_reference_t<reference_t<T>, value_type_t<T>&>;

  // [std.iterator.tags], iterator tags:
  struct output_iterator_tag { };
  struct input_iterator_tag { };
  struct forward_iterator_tag : input_iterator_tag { };
  struct bidirectional_iterator_tag : forward_iterator_tag { };
  struct random_access_iterator_tag : bidirectional_iterator_tag { };

  // [iterator.operations], iterator operations:
  namespace {
    constexpr unspecified advance = unspecified;
    constexpr unspecified distance = unspecified;
    constexpr unspecified next = unspecified;
    constexpr unspecified prev = unspecified;
  }

  // [iterators.predef], predefined iterators and sentinels:

  // [iterators.reverse], reverse iterators:
  template <BidirectionalIterator I> class reverse_iterator;

  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator==(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator!=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);

  template <class I1, class I2>
      requires SizedSentinel<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <RandomAccessIterator I>
    constexpr reverse_iterator<I> operator+(
      difference_type_t<I> n,
      const reverse_iterator<I>& x);

  template <BidirectionalIterator I>
    constexpr reverse_iterator<I> make_reverse_iterator(I i);

  // [iterators.insert], insert iterators:
  template <class Container> class back_insert_iterator;
  template <class Container>
    back_insert_iterator<Container> back_inserter(Container& x);

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

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

  // [iterators.move], move iterators and sentinels:
  template <InputIterator I> class move_iterator;
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator==(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator!=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);

  template <class I1, class I2>
      requires SizedSentinel<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const move_iterator<I1>& x,
      const move_iterator<I2>& y);
  template <RandomAccessIterator I>
    constexpr move_iterator<I> operator+(
      difference_type_t<I> n,
      const move_iterator<I>& x);
  template <InputIterator I>
    constexpr move_iterator<I> make_move_iterator(I i);

  template <Semiregular S> class move_sentinel;

  template <class I, Sentinel<I> S>
    constexpr bool operator==(
      const move_iterator<I>& i, const move_sentinel<S>& s);
  template <class I, Sentinel<I> S>
    constexpr bool operator==(
      const move_sentinel<S>& s, const move_iterator<I>& i);
  template <class I, Sentinel<I> S>
    constexpr bool operator!=(
      const move_iterator<I>& i, const move_sentinel<S>& s);
  template <class I, Sentinel<I> S>
    constexpr bool operator!=(
      const move_sentinel<S>& s, const move_iterator<I>& i);

  template <class I, SizedSentinel<I> S>
    constexpr difference_type_t<I> operator-(
      const move_sentinel<S>& s, const move_iterator<I>& i);
  template <class I, SizedSentinel<I> S>
    constexpr difference_type_t<I> operator-(
      const move_iterator<I>& i, const move_sentinel<S>& s);

  template <Semiregular S>
    constexpr move_sentinel<S> make_move_sentinel(S s);

  // [iterators.common], common iterators:
  template <Iterator I, Sentinel<I> S>
    requires !Same<I, S>
  class common_iterator;

  template <Readable I, class S>
  struct value_type<common_iterator<I, S>>;

  template <InputIterator I, class S>
  struct iterator_category<common_iterator<I, S>>;

  template <ForwardIterator I, class S>
  struct iterator_category<common_iterator<I, S>>;

  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
  bool operator==(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
    requires EqualityComparableWith<I1, I2>
  bool operator==(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
  bool operator!=(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

  template <class I2, SizedSentinel<I2> I1, SizedSentinel<I2> S1, SizedSentinel<I1> S2>
  difference_type_t<I2> operator-(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

  // [default.sentinels], default sentinels:
  class default_sentinel;

  // [iterators.counted], counted iterators:
  template <Iterator I> class counted_iterator;

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator==(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  constexpr bool operator==(
    const counted_iterator<auto>& x, default_sentinel);
  constexpr bool operator==(
    default_sentinel, const counted_iterator<auto>& x);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator!=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  constexpr bool operator!=(
    const counted_iterator<auto>& x, default_sentinel y);
  constexpr bool operator!=(
    default_sentinel x, const counted_iterator<auto>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator<(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator<=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator>(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator>=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I>
    constexpr difference_type_t<I> operator-(
      const counted_iterator<I>& x, default_sentinel y);
  template <class I>
    constexpr difference_type_t<I> operator-(
      default_sentinel x, const counted_iterator<I>& y);
  template <RandomAccessIterator I>
    constexpr counted_iterator<I>
      operator+(difference_type_t<I> n, const counted_iterator<I>& x);
  template <Iterator I>
    constexpr counted_iterator<I> make_counted_iterator(I i, difference_type_t<I> n);

  // [unreachable.sentinels], unreachable sentinels:
  class unreachable;
  template <Iterator I>
    constexpr bool operator==(const I&, unreachable) noexcept;
  template <Iterator I>
    constexpr bool operator==(unreachable, const I&) noexcept;
  template <Iterator I>
    constexpr bool operator!=(const I&, unreachable) noexcept;
  template <Iterator I>
    constexpr bool operator!=(unreachable, const I&) noexcept;

  // [dangling.wrappers], dangling wrapper:
  template <class T> class dangling;

  // [iterators.stream], stream iterators:
  template <class T, class charT = char, class traits = char_traits<charT>,
      class Distance = ptrdiff_t>
  class istream_iterator;
  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);
  template <class T, class charT, class traits, class Distance>
    bool operator==(default_sentinel x,
            const istream_iterator<T, charT, traits, Distance>& y);
  template <class T, class charT, class traits, class Distance>
    bool operator==(const istream_iterator<T, charT, traits, Distance>& x,
            default_sentinel y);
  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);
  template <class T, class charT, class traits, class Distance>
   bool operator!=(default_sentinel x,
            const istream_iterator<T, charT, traits, Distance>& y);
  template <class T, class charT, class traits, class Distance>
    bool operator!=(const istream_iterator<T, charT, traits, Distance>& x,
            default_sentinel y);

  template <class T, class charT = char, class traits = char_traits<charT>>
      class ostream_iterator;

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

  template <class charT, class traits = char_traits<charT> >
    class ostreambuf_iterator;
}}}}

namespace std {
  // [iterator.stdtraits], iterator traits:
  template <experimental::ranges::Iterator Out>
    struct iterator_traits<Out>;
  template <experimental::ranges::InputIterator In>
    struct iterator_traits<In>;
  template <experimental::ranges::InputIterator In>
      requires experimental::ranges::Sentinel<In, In>
    struct iterator_traits;
}

9.3 Iterator requirements [iterator.requirements]

9.3.1 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. All input iterators i support the expression *i, resulting in a value of some object type T, called the value type of the iterator. All output iterators support the expression *i = o where o is a value of some type that is in the set of types that are writable to the particular iterator type of i. 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 five categories of iterators, according to the operations defined on them: input iterators, output iterators, forward iterators, bidirectional iterators and random access iterators, as shown in Table [tab:iterators.relations].

Table 8 — Relations among iterator categories
Random Access Bidirectional Forward Input
Output

The five categories of iterators correspond to the iterator concepts InputIterator, OutputIterator, ForwardIterator, BidirectionalIterator, and RandomAccessIterator, respectively. The generic term iterator refers to any type that satisfies 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.

Iterators that further satisfy the requirements of output iterators are called mutable iterators. Nonmutable iterators are referred to as constant iterators.

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

An iterator and a sentinel denoting a range are comparable. The types of a sentinel and an iterator that denote a range must satisfy Sentinel ([iterators.sentinel]). 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 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 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 pointed to by the result of incrementing i n times.

A range [i,s) is valid if and only if s is reachable from 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 functions in the library 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).

Destruction of an iterator may invalidate pointers and references previously obtained from that iterator.

An invalid iterator is an iterator that may be singular.3

This definition applies to pointers, since pointers are iterators. The effect of dereferencing an iterator that has been invalidated is undefined.

9.3.2 Customization points [iterator.custpoints]

9.3.2.1 iter_move [iterator.custpoints.iter_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:

  • static_cast<decltype(iter_move(E))>(iter_move(E)), if that expression is well-formed when evaluated in a context that does not include ranges::iter_move but does include the lookup set produced by argument-dependent lookup ( ISO/IEC 14882:2014 §[basic.lookup.argdep]).

  • Otherwise, if the expression *E is well-formed:

    • if *E is an lvalue, std::move(*E);

    • otherwise, static_cast<decltype(*E)>(*E).

  • Otherwise, ranges::iter_move(E) is ill-formed.

If ranges::iter_move(E) does not equal *E, the program is ill-formed with no diagnostic required.

9.3.2.2 iter_swap [iterator.custpoints.iter_swap]

The name iter_swap denotes a customization point object ([customization.point.object]). 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 well-formed when evaluated in a context that does not include ranges::iter_swap but does include the lookup set produced by argument-dependent lookup ( ISO/IEC 14882:2014 §[basic.lookup.argdep]) and the following declaration:

    void iter_swap(auto, auto) = delete;
    
  • Otherwise, if the types of E1 and E2 both satisfy Readable, and if the reference type of E1 is swappable with ([concepts.lib.corelang.swappable]) the reference type of E2, then ranges::swap(*E1, *E2)

  • Otherwise, if the types T1 and T2 of E1 and E2 satisfy IndirectlyMovableStorable<T1, T2> && IndirectlyMovableStorable<T2, T1>, (void)(*E1 = iter_exchange_move(E2, E1)), except that E1 is evaluated only once.

  • Otherwise, ranges::iter_swap(E1, E2) is ill-formed.

If ranges::iter_swap(E1, E2) does not swap the values denoted by the expressions E1 and E2, the program is ill-formed with no diagnostic required.

iter_exchange_move is an exposition-only function specified as: template <class X, class Y> constexpr value_type_t<remove_reference_t<X>> iter_exchange_move(X&& x, Y&& y) noexcept(see below);

Effects: Equivalent to:

value_type_t<remove_reference_t<X>> old_value(iter_move(x));
*x = iter_move(y);
return old_value;

Remarks: The expression in the noexcept is equivalent to:

NE(remove_reference_t<X>, remove_reference_t<Y>) &&
NE(remove_reference_t<Y>, remove_reference_t<X>)

Where NE(T1, T2) is the expression:

is_nothrow_constructible<value_type_t<T1>, rvalue_reference_t<T1>>::value &&
is_nothrow_assignable<value_type_t<T1>&, rvalue_reference_t<T1>>::value &&
is_nothrow_assignable<reference_t<T1>, rvalue_reference_t<T2>>::value &&
is_nothrow_assignable<reference_t<T1>, value_type_t<T2>>::value> &&
is_nothrow_move_constructible<value_type_t<T1>>::value &&
noexcept(ranges::iter_move(declval<T1&>()))

9.3.3 Iterator associated types [iterator.assoc.types]

To implement algorithms only in terms of iterators, it is often necessary to determine the value and difference types that correspond to a particular iterator type. Accordingly, it is required that if WI is the name of a type that satisfies the WeaklyIncrementable concept ([iterators.weaklyincrementable]), R is the name of a type that satisfies the Readable concept ([iterators.readable]), and II is the name of a type that satisfies the InputIterator concept ([iterators.input]) concept, the types

difference_type_t<WI>
value_type_t<R>
iterator_category_t<II>

be defined as the iterator's difference type, value type and iterator category, respectively.

9.3.3.1 difference_type [iterator.assoc.types.difference_type]

difference_type_t<T> is implemented as if:

  template <class> struct difference_type { };

  template <class T>
  struct difference_type<T*>
    : enable_if<is_object<T>::value, ptrdiff_t> { };

  template <class I>
  struct difference_type<const I> : difference_type<decay_t<I>> { };

  template <class T>
    requires requires { typename T::difference_type; }
  struct difference_type<T> {
    using 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 difference_type<T>
    : make_signed< decltype(declval<T>() - declval<T>()) > {
  };

  template <class T> using difference_type_t
    = typename difference_type<T>::type;

Users may specialize difference_type on user-defined types.

9.3.3.2 value_type [iterator.assoc.types.value_type]

A Readable type has an associated value type that can be accessed with the value_type_t alias template.

  template <class> struct value_type { };

  template <class T>
  struct value_type<T*>
    : enable_if<is_object<T>::value, remove_cv_t<T>> { };

  template <class I>
    requires is_array<I>::value
  struct value_type<I> : value_type<decay_t<I>> { };

  template <class I>
  struct value_type<const I> : value_type<decay_t<I>> { };

  template <class T>
    requires requires { typename T::value_type; }
  struct value_type<T>
    : enable_if<is_object<typename T::value_type>::value, typename T::value_type> { };

  template <class T>
    requires requires { typename T::element_type; }
  struct value_type<T>
    : enable_if<
        is_object<typename T::element_type>::value,
        remove_cv_t<typename T::element_type>>
    { };

  template <class T> using value_type_t
    = typename value_type<T>::type;

If a type I has an associated value type, then value_type<I>::type shall name the value type. Otherwise, there shall be no nested type type.

The value_type class template may be specialized on user-defined types.

When instantiated with a type I such that I::value_type is valid and denotes a type, value_type<I>::type names that type, unless it is not an object type ( ISO/IEC 14882:2014 §[basic.types]) in which case value_type<I> shall have no nested type type. [ 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 ]

When instantiated with a type I such that I::element_type is valid and denotes a type, value_type<I>::type names the type remove_cv_t<I::element_type>, unless it is not an object type ( ISO/IEC 14882:2014 §[basic.types]) in which case value_type<I> shall have no nested type type. [ 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 ]

9.3.3.3 iterator_category [iterator.assoc.types.iterator_category]

iterator_category_t<T> is implemented as if:

  template <class> struct iterator_category { };

  template <class T>
  struct iterator_category<T*>
    : enable_if<is_object<T>::value, random_access_iterator_tag> { };

  template <class T>
  struct iterator_category<T const> : iterator_category<T> { };

  template <class T>
    requires requires { typename T::iterator_category; }
  struct iterator_category<T> {
    using type = see below;
  };

  template <class T> using iterator_category_t
    = typename iterator_category<T>::type;

Users may specialize iterator_category on user-defined types.

If T::iterator_category is valid and denotes a type, then the type iterator_category<T>::type is computed as follows:

  • If T::iterator_category is the same as or derives from std::random_access_iterator_tag, iterator_category<T>::type is ranges::random_access_iterator_tag.

  • Otherwise, if T::iterator_category is the same as or derives from std::bidirectional_iterator_tag, iterator_category<T>::type is ranges::bidirectional_iterator_tag.

  • Otherwise, if T::iterator_category is the same as or derives from std::forward_iterator_tag, iterator_category<T>::type is ranges::forward_iterator_tag.

  • Otherwise, if T::iterator_category is the same as or derives from std::input_iterator_tag, iterator_category<T>::type is ranges::input_iterator_tag.

  • Otherwise, if T::iterator_category is the same as or derives from std::output_iterator_tag, iterator_category<T> has no nested type.

  • Otherwise, iterator_category<T>::type is T::iterator_category

rvalue_reference_t<T> is implemented as if:

template <dereferenceable T> requires see below using rvalue_reference_t = decltype(ranges::iter_move(declval<T&>()));

The expression in the requires clause is equivalent to:

requires(T& t) { { ranges::iter_move(t) } -> auto&&; }

9.3.4 Concept Readable [iterators.readable]

The Readable concept is satisfied by types that are readable by applying operator* including pointers, smart pointers, and iterators.

  template <class In>
  concept bool Readable =
    requires {
      typename value_type_t<In>;
      typename reference_t<In>;
      typename rvalue_reference_t<In>;
    } &&
    CommonReference<reference_t<In>&&, value_type_t<In>&> &&
    CommonReference<reference_t<In>&&, rvalue_reference_t<In>&&> &&
    CommonReference<rvalue_reference_t<In>&&, const value_type_t<In>&>;

9.3.5 Concept Writable [iterators.writable]

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

  template <class Out, class T>
  concept bool 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 reference_t<Out>&&>(*o) =
        std::forward<T>(t); // not required to be equality preserving
      const_cast<const 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. Writable<Out, T> is satisfied only if

  • If Readable<Out> && Same<value_type_t<Out>, decay_t<T>> is satisfied, 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 ( ISO/IEC 14882:2014 §[basic.lval]), the resulting state of the object it denotes is valid but unspecified ( ISO/IEC 14882:2014 §[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 ]

9.3.6 Concept WeaklyIncrementable [iterators.weaklyincrementable]

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 bool WeaklyIncrementable =
    Semiregular<I> &&
    requires(I i) {
      typename difference_type_t<I>;
      requires SignedIntegral<difference_type_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. WeaklyIncrementable<I> is satisfied 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 &++i is equal to &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 ]

9.3.7 Concept Incrementable [iterators.incrementable]

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 requirement supersedes the annotations on the increment expressions in the definition of WeaklyIncrementable.  — end note ]

  template <class I>
  concept bool Incrementable =
    Regular<I> &&
    WeaklyIncrementable<I> &&
    requires(I i) {
      { i++ } -> Same<I>&&;
    };

Let a and b be incrementable objects of type I. Incrementable<I> is satisfied only if

  • If bool(a == b) then bool(a++ == b).

  • If bool(a == b) then bool((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 satisfy Incrementable. — end note ]

9.3.8 Concept Iterator [iterators.iterator]

The Iterator concept forms the basis of the iterator concept taxonomy; every iterator satisfies the Iterator requirements. This concept specifies operations for dereferencing and incrementing an iterator. Most algorithms will require additional operations to compare iterators with sentinels ([iterators.sentinel]), to read ([iterators.input]) or write ([iterators.output]) values, or to provide a richer set of iterator movements ([iterators.forward], [iterators.bidirectional], [iterators.random.access]).)

  template <class I>
  concept bool Iterator =
    requires(I i) {
      { *i } -> auto&&; // Requires: i is dereferenceable
    } &&
    WeaklyIncrementable<I>;

Note: The requirement that the result of dereferencing the iterator is deducible from auto&& means that it cannot be void. — end note ]

9.3.9 Concept Sentinel [iterators.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 bool Sentinel = Semiregular<S> && Iterator<I> && WeaklyEqualityComparableWith<S, I>;

Let s and i be values of type S and I such that [i,s) denotes a range. Types S and I satisfy 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 == can change over time. Given an iterator i and sentinel s such that [i,s) denotes a range and i != s, [i,s) is not required to continue to denote a range after incrementing any iterator equal to i. Consequently, i == s is no longer required to be well-defined.

9.3.10 Concept SizedSentinel [iterators.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 bool 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<difference_type_t<I>>&&; { i - s } -> Same<difference_type_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. SizedSentinel<S, I> is satisfied only if:

  • If N is representable by difference_type_t<I>, then s - i is well-defined and equals N.

  • If -N is representable by difference_type_t<I>, then i - s is well-defined and equals -N.

Note: disable_sized_sentinel provides a mechanism to enable use of sentinels and iterators with the library that meet the syntactic requirements but do not in fact satisfy SizedSentinel. A program that instantiates a library template that requires SizedSentinel with an iterator type I and sentinel type S that meet the syntactic requirements of SizedSentinel<S, I> but do not satisfy SizedSentinel is ill-formed with no diagnostic required unless disable_sized_sentinel<S, I> evaluates to true ([structure.requirements]).  — end note ]

Note: The SizedSentinel concept is satisfied by pairs of RandomAccessIterators ([iterators.random.access]) and by counted iterators and their sentinels ([counted.iterator]). — end note ]

9.3.11 Concept InputIterator [iterators.input]

The InputIterator concept is a refinement of Iterator ([iterators.iterator]). It defines requirements for a type whose referenced values can be read (from the requirement for Readable ([iterators.readable])) and which can be both pre- and post-incremented. [ Note: Unlike in ISO/IEC 14882, input iterators are not required to satisfy EqualityComparable ([concepts.lib.compare.equalitycomparable]). — end note ]

  template <class I>
  concept bool InputIterator =
    Iterator<I> &&
    Readable<I> &&
    requires { typename iterator_category_t<I>; } &&
    DerivedFrom<iterator_category_t<I>, input_iterator_tag>;

9.3.12 Concept OutputIterator [iterators.output]

The OutputIterator concept is a refinement of Iterator ([iterators.iterator]). It defines requirements for a type that can be used to write values (from the requirement for Writable ([iterators.writable])) and which can be both pre- and post-incremented. However, output iterators are not required to satisfy EqualityComparable.

  template <class I, class T>
  concept bool 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. OutputIterator<I, T> is satisfied 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. Algorithms that take output iterators can be used with ostreams as the destination for placing data through the ostream_iterator class as well as with insert iterators and insert pointers.  — end note ]

9.3.13 Concept ForwardIterator [iterators.forward]

The ForwardIterator concept refines InputIterator ([iterators.input]), adding equality comparison and the multi-pass guarantee, specified below.

  template <class I>
  concept bool ForwardIterator =
    InputIterator<I> &&
    DerivedFrom<iterator_category_t<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 ([](X x){++x;}(a), *a) is equivalent to the expression *a.

Note: The requirement that a == b implies ++a == ++b (which is not true for weaker iterators) 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 ]

9.3.14 Concept BidirectionalIterator [iterators.bidirectional]

The BidirectionalIterator concept refines ForwardIterator ([iterators.forward]), and adds the ability to move an iterator backward as well as forward.

  template <class I>
  concept bool BidirectionalIterator =
    ForwardIterator<I> &&
    DerivedFrom<iterator_category_t<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 s such that ++s == r. Decrementable iterators r shall be in the domain of the expressions --r and r--.

Let a and b be decrementable objects of type I. BidirectionalIterator<I> is satisfied only if:

  • &--a == &a.

  • If bool(a == b), then bool(a-- == b).

  • If bool(a == b), then after evaluating both a-- and --b, bool(a == b) still holds.

  • If a is incrementable and bool(a == b), then bool(--(++a) == b).

  • If bool(a == b), then bool(++(--a) == b).

9.3.15 Concept RandomAccessIterator [iterators.random.access]

The RandomAccessIterator concept refines BidirectionalIterator ([iterators.bidirectional]) and adds support for constant-time advancement with +=, +, -=, and -, and the computation of distance in constant time with -. Random access iterators also support array notation via subscripting.

  template <class I>
  concept bool RandomAccessIterator =
    BidirectionalIterator<I> &&
    DerivedFrom<iterator_category_t<I>, random_access_iterator_tag> &&
    StrictTotallyOrdered<I> &&
    SizedSentinel<I, I> &&
    requires(I i, const I j, const difference_type_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];
      requires Same<decltype(j[n]), reference_t<I>>;
    };

Let a and b be valid iterators of type I such that b is reachable from a. Let n be the smallest value of type difference_type_t<I> such that after n applications of ++a, then bool(a == b). RandomAccessIterator<I> is satisfied only if:

  • (a += n) is equal to b.

  • &(a += n) is equal to &a.

  • (a + n) is equal to (a += n).

  • For any two positive integers x and y, if a + (x + y) is valid, then a + (x + y) is equal to (a + x) + y.

  • a + 0 is equal to a.

  • If (a + (n - 1)) is valid, then a + n is equal to ++(a + (n - 1)).

  • (b += -n) is equal to a.

  • (b -= n) is equal to a.

  • &(b -= n) is equal to &b.

  • (b - n) is equal to (b -= n).

  • If b is dereferenceable, then a[n] is valid and is equal to *b.

9.4 Indirect callable requirements [indirectcallable]

9.4.1 General [indirectcallable.general]

There are several concepts that group requirements of algorithms that take callable objects ( ISO/IEC 14882:2014 §[func.require]) as arguments.

9.4.2 Indirect callables [indirectcallable.indirectinvocable]

The indirect callable concepts are used to constrain those algorithms that accept callable objects ( ISO/IEC 14882:2014 §[func.def]) as arguments.

  template <class F, class I>
  concept bool IndirectUnaryInvocable =
    Readable<I> &&
    CopyConstructible<F> &&
    Invocable<F&, value_type_t<I>&> &&
    Invocable<F&, reference_t<I>> &&
    Invocable<F&, iter_common_reference_t<I>> &&
    CommonReference<
      result_of_t<F&(value_type_t<I>&)>,
      result_of_t<F&(reference_t<I>&&)>>;

  template <class F, class I>
  concept bool IndirectRegularUnaryInvocable =
    Readable<I> &&
    CopyConstructible<F> &&
    RegularInvocable<F&, value_type_t<I>&> &&
    RegularInvocable<F&, reference_t<I>> &&
    RegularInvocable<F&, iter_common_reference_t<I>> &&
    CommonReference<
      result_of_t<F&(value_type_t<I>&)>,
      result_of_t<F&(reference_t<I>&&)>>;

  template <class F, class I>
  concept bool IndirectUnaryPredicate =
    Readable<I> &&
    CopyConstructible<F> &&
    Predicate<F&, value_type_t<I>&> &&
    Predicate<F&, reference_t<I>> &&
    Predicate<F&, iter_common_reference_t<I>>;

  template <class F, class I1, class I2 = I1>
  concept bool IndirectRelation =
    Readable<I1> && Readable<I2> &&
    CopyConstructible<F> &&
    Relation<F&, value_type_t<I1>&, value_type_t<I2>&> &&
    Relation<F&, value_type_t<I1>&, reference_t<I2>> &&
    Relation<F&, reference_t<I1>, value_type_t<I2>&> &&
    Relation<F&, reference_t<I1>, reference_t<I2>> &&
    Relation<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

  template <class F, class I1, class I2 = I1>
  concept bool IndirectStrictWeakOrder =
    Readable<I1> && Readable<I2> &&
    CopyConstructible<F> &&
    StrictWeakOrder<F&, value_type_t<I1>&, value_type_t<I2>&> &&
    StrictWeakOrder<F&, value_type_t<I1>&, reference_t<I2>> &&
    StrictWeakOrder<F&, reference_t<I1>, value_type_t<I2>&> &&
    StrictWeakOrder<F&, reference_t<I1>, reference_t<I2>> &&
    StrictWeakOrder<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

  template <class> struct indirect_result_of { };

  template <class F, class... Is>
    requires Invocable<F, reference_t<Is>...>
  struct indirect_result_of<F(Is...)> :
    result_of<F(reference_t<Is>&&...)> { };

9.4.3 Class template projected [projected]

The projected class template is intended for use when specifying the constraints of algorithms that accept callable objects and projections ([defns.projection]). It bundles a Readable type I and a function Proj into a new Readable type whose reference type is the result of applying Proj to the reference_t of I.

  template <Readable I, IndirectRegularUnaryInvocable<I> Proj>
  struct projected {
    using value_type = remove_cv_t<remove_reference_t<indirect_result_of_t<Proj&(I)>>>;
    indirect_result_of_t<Proj&(I)> operator*() const;
  };

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

Note: projected is only used to ease constraints specification. Its member function need not be defined. — end note ]

9.5 Common algorithm requirements [commonalgoreq]

9.5.1 General [commonalgoreq.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 equal_to<> and less<> ([comparisons]) function types used in the concepts below impose additional constraints on their arguments beyond those that appear explicitly in the concepts' bodies. equal_to<> requires its arguments satisfy EqualityComparableWith ([concepts.lib.compare.equalitycomparable]), and less<> requires its arguments satisfy StrictTotallyOrderedWith ([concepts.lib.compare.stricttotallyordered]). — end note ]

9.5.2 Concept IndirectlyMovable [commonalgoreq.indirectlymovable]

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 bool IndirectlyMovable =
    Readable<In> &&
    Writable<Out, 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 bool IndirectlyMovableStorable =
    IndirectlyMovable<In, Out> &&
    Writable<Out, value_type_t<In>> &&
    Movable<value_type_t<In>> &&
    Constructible<value_type_t<In>, rvalue_reference_t<In>> &&
    Assignable<value_type_t<In>&, rvalue_reference_t<In>>;

9.5.3 Concept IndirectlyCopyable [commonalgoreq.indirectlycopyable]

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 bool IndirectlyCopyable =
    Readable<In> &&
    Writable<Out, 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 bool IndirectlyCopyableStorable =
    IndirectlyCopyable<In, Out> &&
    Writable<Out, const value_type_t<In>&> &&
    Copyable<value_type_t<In>> &&
    Constructible<value_type_t<In>, reference_t<In>> &&
    Assignable<value_type_t<In>&, reference_t<In>>;

9.5.4 Concept IndirectlySwappable [commonalgoreq.indirectlyswappable]

The IndirectlySwappable concept specifies a swappable relationship between the values referenced by two Readable types.

  template <class I1, class I2 = I1>
  concept bool IndirectlySwappable =
    Readable<I1> && Readable<I2> &&
    requires(I1&& i1, I2&& i2) {
      ranges::iter_swap(std::forward<I1>(i1), std::forward<I2>(i2));
      ranges::iter_swap(std::forward<I2>(i2), std::forward<I1>(i1));
      ranges::iter_swap(std::forward<I1>(i1), std::forward<I1>(i1));
      ranges::iter_swap(std::forward<I2>(i2), std::forward<I2>(i2));
    };

Given an object i1 of type I1 and an object i2 of type I2, IndirectlySwappable<I1, I2> is satisfied if after ranges::iter_swap(i1, i2), the value of *i1 is equal to the value of *i2 before the call, and vice versa.

9.5.5 Concept IndirectlyComparable [commonalgoreq.indirectlycomparable]

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

  template <class I1, class I2, class R = equal_to<>, class P1 = identity,
    class P2 = identity>
  concept bool IndirectlyComparable =
    IndirectRelation<R, projected<I1, P1>, projected<I2, P2>>;

9.5.6 Concept Permutable [commonalgoreq.permutable]

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

  template <class I>
  concept bool Permutable =
    ForwardIterator<I> &&
    IndirectlyMovableStorable<I, I> &&
    IndirectlySwappable<I, I>;

9.5.7 Concept Mergeable [commonalgoreq.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 = less<>, class P1 = identity, class P2 = identity>
  concept bool Mergeable =
    InputIterator<I1> &&
    InputIterator<I2> &&
    WeaklyIncrementable<Out> &&
    IndirectlyCopyable<I1, Out> &&
    IndirectlyCopyable<I2, Out> &&
    IndirectStrictWeakOrder<R, projected<I1, P1>, projected<I2, P2>>;

9.5.8 Concept Sortable [commonalgoreq.sortable]

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

  template <class I, class R = less<>, class P = identity>
  concept bool Sortable =
    Permutable<I> &&
    IndirectStrictWeakOrder<R, projected<I, P>>;

9.6 Iterator primitives [iterator.primitives]

To simplify the task of defining iterators, the library provides several classes and functions:

9.6.1 Iterator traits [iterator.traits]

For the sake of backwards compatibility, this document specifies the existence of an iterator_traits alias that collects an iterator's associated types. It is defined as if:

  template <InputIterator I> struct __pointer_type {        // exposition only
    using type = add_pointer_t<reference_t<I>>;
  };
  template <InputIterator I>
    requires requires(I i) { { i.operator->() } -> auto&&; }
  struct __pointer_type<I> {                                    // exposition only
    using type = decltype(declval<I>().operator->());
  };
  template <class> struct __iterator_traits { };                // exposition only
  template <Iterator I> struct __iterator_traits<I> {
    using difference_type = difference_type_t<I>;
    using value_type = void;
    using reference = void;
    using pointer = void;
    using iterator_category = output_iterator_tag;
  };
  template <InputIterator I> struct __iterator_traits<I> {  // exposition only
    using difference_type = difference_type_t<I>;
    using value_type = value_type_t<I>;
    using reference = reference_t<I>;
    using pointer = typename __pointer_type<I>::type;
    using iterator_category = iterator_category_t<I>;
  };
  template <class I>
    using iterator_traits = __iterator_traits<I>;

Note: iterator_traits is an alias template to prevent user code from specializing it.  — end note ]

Example: To implement a generic reverse function, a C++ program can do the following:

template <BidirectionalIterator I>
void reverse(I first, I last) {
  difference_type_t<I> n = distance(first, last);
  --n;
  while(n > 0) {
    value_type_t<I> tmp = *first;
    *first++ = *--last;
    *last = tmp;
    n -= 2;
  }
}

 — end example ]

9.6.2 Standard iterator traits [iterator.stdtraits]

To facilitate interoperability between new code using iterators conforming to this document and older code using iterators that conform to the iterator requirements specified in ISO/IEC 14882, three specializations of std::iterator_traits are provided to map the newer iterator categories and associated types to the older ones.

namespace std {
  template <experimental::ranges::Iterator Out>
  struct iterator_traits<Out> {
    using difference_type   = experimental::ranges::difference_type_t<Out>;
    using value_type        = see below;
    using reference         = see below;
    using pointer           = see below;
    using iterator_category = std::output_iterator_tag;
  };
}

The nested type value_type is computed as follows:

  • If Out::value_type is valid and denotes a type, then std::iterator_traits<Out>::value_type is Out::value_type.

  • Otherwise, std::iterator_traits<Out>::value_type is void.

The nested type reference is computed as follows:

  • If Out::reference is valid and denotes a type, then std::iterator_traits<Out>::reference is Out::reference.

  • Otherwise, std::iterator_traits<Out>::reference is void.

The nested type pointer is computed as follows:

  • If Out::pointer is valid and denotes a type, then std::iterator_traits<Out>::pointer is Out::pointer.

  • Otherwise, std::iterator_traits<Out>::pointer is void.

namespace std {
  template <experimental::ranges::InputIterator In>
  struct iterator_traits<In> { };

  template <experimental::ranges::InputIterator In>
    requires experimental::ranges::Sentinel<In, In>
  struct iterator_traits<In> {
    using difference_type   = experimental::ranges::difference_type_t<In>;
    using value_type        = experimental::ranges::value_type_t<In>;
    using reference         = see below;
    using pointer           = see below;
    using iterator_category = see below;
  };
}

The nested type reference is computed as follows:

  • If In::reference is valid and denotes a type, then std::iterator_traits<In>::reference is In::reference.

  • Otherwise, std::iterator_traits<In>::reference is experimental::ranges::reference_t<In>.

The nested type pointer is computed as follows:

  • If In::pointer is valid and denotes a type, then std::iterator_traits<In>::pointer is In::pointer.

  • Otherwise, std::iterator_traits<In>::pointer is experimental::ranges::iterator_traits<In>::pointer.

Let type C be experimental::ranges::iterator_category_t<In>. The nested type std::iterator_traits<In>::iterator_category is computed as follows:

  • If C is the same as or inherits from std::input_iterator_tag or std::output_iterator_tag, std::iterator_traits<In>::iterator_category is C.

  • Otherwise, if experimental::ranges::reference_t<In> is not a reference type, std::iterator_traits<In>::iterator_category is std::input_iterator_tag.

  • Otherwise, if C is the same as or inherits from experimental::ranges::random_access_iterator_tag, std::iterator_traits<In>::iterator_category is std::random_access_iterator_tag.

  • Otherwise, if C is the same as or inherits from experimental::ranges::bidirectional_iterator_tag, std::iterator_traits<In>::iterator_category is std::bidirectional_iterator_tag.

  • Otherwise, if C is the same as or inherits from experimental::ranges::forward_iterator_tag, std::iterator_traits<In>::iterator_category is std::forward_iterator_tag.

  • Otherwise, std::iterator_traits<In>::iterator_category is std::input_iterator_tag.

Note: Some implementations may find it necessary to add additional constraints to these partial specializations to prevent them from being considered for types that conform to the iterator requirements specified in ISO/IEC 14882. — end note ]

9.6.3 Standard iterator tags [std.iterator.tags]

It is often desirable for a function template specialization to find out what is the most specific category of its iterator argument, so that the function can select the most efficient algorithm at compile time. To facilitate this, the library introduces category tag classes which can be used as compile time tags for algorithm selection. [ Note: The preferred way to dispatch to more specialized algorithm implementations is with concept-based overloading. — end note ] The category tags are: input_iterator_tag, output_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag and random_access_iterator_tag. For every input iterator of type I, iterator_category_t<I> shall be defined to be the most specific category tag that describes the iterator's behavior.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  struct output_iterator_tag { };
  struct input_iterator_tag { };
  struct forward_iterator_tag : input_iterator_tag { };
  struct bidirectional_iterator_tag : forward_iterator_tag { };
  struct random_access_iterator_tag : bidirectional_iterator_tag { };
}}}}

Note: The output_iterator_tag is provided for the sake of backward compatibility.  — end note ]

Example: For a program-defined iterator BinaryTreeIterator, it could be included into the bidirectional iterator category by specializing the difference_type, value_type, and iterator_category templates:

template <class T> struct difference_type<BinaryTreeIterator<T>> {
  using type = ptrdiff_t;
};
template <class T> struct value_type<BinaryTreeIterator<T>> {
  using type = T;
};
template <class T> struct iterator_category<BinaryTreeIterator<T>> {
  using type = bidirectional_iterator_tag;
};

 — end example ]

9.6.4 Iterator operations [iterator.operations]

Since only types that satisfy RandomAccessIterator provide the + operator, and types that satisfy SizedSentinel provide the - operator, the library provides customization point objects ([customization.point.object]) advance, distance, next, and prev. These customization point objects use + and - for random access iterators and ranges that satisfy SizedSentinel (and are, therefore, constant time for them); for output, input, forward and bidirectional iterators they use ++ to provide linear time implementations.

The name advance denotes a customization point object ([customization.point.object]). It has the following function call operators:

template <Iterator I> constexpr void operator()(I& i, difference_type_t<I> n) const;

Requires: n shall be negative only for bidirectional iterators.

Effects: For random access iterators, equivalent to i += n. Otherwise, increments (or decrements for negative n) iterator i by n.

template <Iterator I, Sentinel<I> S> constexpr void operator()(I& i, S bound) const;

Requires: If Assignable<I&, S> is not satisfied, [i,bound) shall denote a range.

Effects:

  • If Assignable<I&, S> is satisfied, equivalent to i = std::move(bound).

  • Otherwise, if SizedSentinel<S, I> is satisfied, equivalent to advance(i, bound - i).

  • Otherwise, increments i until i == bound.

template <Iterator I, Sentinel<I> S> constexpr difference_type_t<I> operator()(I& i, difference_type_t<I> n, S bound) const;

Requires: If n > 0, [i,bound) shall denote a range. If n == 0, [i,bound) or [bound,i) shall denote a range. If n < 0, [bound,i) shall denote a range and (BidirectionalIterator<I> && Same<I, S>) shall be satisfied.

Effects:

  • If SizedSentinel<S, I> is satisfied:

    • If |n| >= |bound - i|, equivalent to advance(i, bound).

    • Otherwise, equivalent to advance(i, n).

  • Otherwise, increments (or decrements for negative n) iterator i either n times or until i == bound, whichever comes first.

Returns: n - M, where M is the distance from the starting position of i to the ending position.

The name distance denotes a customization point object. It has the following function call operators:

template <Iterator I, Sentinel<I> S> constexpr difference_type_t<I> operator()(I first, S last) const;

Requires: [first,last) shall denote a range, or (Same<S, I> && SizedSentinel<S, I>) shall be satisfied and [last,first) shall denote a range.

Effects: If SizedSentinel<S, I> is satisfied, returns (last - first); otherwise, returns the number of increments needed to get from first to last.

template <Range R> constexpr difference_type_t<iterator_t<R>> operator()(R&& r) const;

Effects: Equivalent to: return distance(ranges::begin(r), ranges::end(r)); ([range.access])

Remarks: Instantiations of this member function template may be ill-formed if the declarations in <experimental/ranges/range> are not in scope at the point of instantiation ( ISO/IEC 14882:2014 §[temp.point]).

template <SizedRange R> constexpr difference_type_t<iterator_t<R>> operator()(R&& r) const;

Effects: Equivalent to: return ranges::size(r); ([range.primitives.size])

Remarks: Instantiations of this member function template may be ill-formed if the declarations in <experimental/ranges/range> are not in scope at the point of instantiation ( ISO/IEC 14882:2014 §[temp.point]).

The name next denotes a customization point object. It has the following function call operators:

template <Iterator I> constexpr I operator()(I x) const;

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

template <Iterator I> constexpr I operator()(I x, difference_type_t<I> n) const;

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

template <Iterator I, Sentinel<I> S> constexpr I operator()(I x, S bound) const;

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

template <Iterator I, Sentinel<I> S> constexpr I operator()(I x, difference_type_t<I> n, S bound) const;

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

The name prev denotes a customization point object. It has the following function call operators:

template <BidirectionalIterator I> constexpr I operator()(I x) const;

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

template <BidirectionalIterator I> constexpr I operator()(I x, difference_type_t<I> n) const;

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

template <BidirectionalIterator I> constexpr I operator()(I x, difference_type_t<I> n, I bound) const;

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

9.7 Iterator adaptors [iterators.predef]

9.7.1 Reverse iterators [iterators.reverse]

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. The fundamental relation between a reverse iterator and its corresponding underlying iterator i is established by the identity: *make_reverse_iterator(i) == *prev(i).

9.7.1.1 Class template reverse_iterator [reverse.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <BidirectionalIterator I>
  class reverse_iterator {
  public:
    using iterator_type = I;
    using difference_type = difference_type_t<I>;
    using value_type = value_type_t<I>;
    using iterator_category = iterator_category_t<I>;
    using reference = reference_t<I>;
    using pointer = I;

    constexpr reverse_iterator();
    explicit constexpr reverse_iterator(I x);
    constexpr reverse_iterator(const reverse_iterator<ConvertibleTo<I>>& i);
    constexpr reverse_iterator& operator=(const reverse_iterator<ConvertibleTo<I>>& i);

    constexpr I base() const;
    constexpr reference operator*() const;
    constexpr pointer operator->() const;

    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
      requires RandomAccessIterator<I>;
    constexpr reverse_iterator& operator+=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr reverse_iterator  operator- (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr reverse_iterator& operator-=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr reference operator[](difference_type n) const
      requires RandomAccessIterator<I>;

    friend constexpr rvalue_reference_t<I> iter_move(const reverse_iterator& i)
      noexcept(see below);
    template <IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<I2>& y)
        noexcept(see below);

  private:
    I current; // exposition only
  };

  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator==(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator!=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires SizedSentinel<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <RandomAccessIterator I>
    constexpr reverse_iterator<I> operator+(
      difference_type_t<I> n,
      const reverse_iterator<I>& x);

  template <BidirectionalIterator I>
    constexpr reverse_iterator<I> make_reverse_iterator(I i);
}}}}

9.7.1.2 reverse_iterator operations [reverse.iter.ops]

9.7.1.2.1 reverse_iterator constructor [reverse.iter.cons]

constexpr reverse_iterator();

Effects: Value-initializes current. 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 I.

explicit constexpr reverse_iterator(I x);

Effects: Initializes current with x.

constexpr reverse_iterator(const reverse_iterator<ConvertibleTo<I>>& i);

Effects: Initializes current with i.current.

9.7.1.2.2 reverse_iterator::operator= [reverse.iter.op=]

constexpr reverse_iterator& operator=(const reverse_iterator<ConvertibleTo<I>>& i);

Effects: Assigns i.current to current.

Returns: *this.

9.7.1.2.3 Conversion [reverse.iter.conv]

constexpr I base() const;

Returns: current.

9.7.1.2.4 operator* [reverse.iter.op.star]

constexpr reference operator*() const;

Effects: Equivalent to: return *prev(current);

9.7.1.2.5 operator-> [reverse.iter.opref]

constexpr pointer operator->() const;

Effects: Equivalent to: return prev(current);

9.7.1.2.6 operator++ [reverse.iter.op++]

constexpr reverse_iterator& operator++();

Effects: -- current;

Returns: *this.

constexpr reverse_iterator operator++(int);

Effects:

reverse_iterator tmp = *this;
--current;
return tmp;

9.7.1.2.7 operator-- [reverse.iter.op--]

constexpr reverse_iterator& operator--();

Effects: ++current

Returns: *this.

constexpr reverse_iterator operator--(int);

Effects:

reverse_iterator tmp = *this;
++current;
return tmp;

9.7.1.2.8 operator+ [reverse.iter.op+]

constexpr reverse_iterator operator+(difference_type n) const requires RandomAccessIterator<I>;

Returns: reverse_iterator(current-n).

9.7.1.2.9 operator+= [reverse.iter.op+=]

constexpr reverse_iterator& operator+=(difference_type n) requires RandomAccessIterator<I>;

Effects: current -= n;

Returns: *this.

9.7.1.2.10 operator- [reverse.iter.op-]

constexpr reverse_iterator operator-(difference_type n) const requires RandomAccessIterator<I>;

Returns: reverse_iterator(current+n).

9.7.1.2.11 operator-= [reverse.iter.op-=]

constexpr reverse_iterator& operator-=(difference_type n) requires RandomAccessIterator<I>;

Effects: current += n;

Returns: *this.

9.7.1.2.12 operator[] [reverse.iter.opindex]

constexpr reference operator[]( difference_type n) const requires RandomAccessIterator<I>;

Returns: current[-n-1].

9.7.1.2.13 operator== [reverse.iter.op==]

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator==( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

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

9.7.1.2.14 operator!= [reverse.iter.op!=]

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator!=( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current != y.current;

9.7.1.2.15 operator< [reverse.iter.op<]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current > y.current;

9.7.1.2.16 operator> [reverse.iter.op>]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current < y.current;

9.7.1.2.17 operator>= [reverse.iter.op>=]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>=( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current <= y.current;

9.7.1.2.18 operator<= [reverse.iter.op<=]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<=( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current >= y.current;

9.7.1.2.19 operator- [reverse.iter.opdiff]

template <class I1, class I2> requires SizedSentinel<I1, I2> constexpr difference_type_t<I2> operator-( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

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

9.7.1.2.20 operator+ [reverse.iter.opsum]

template <RandomAccessIterator I> constexpr reverse_iterator<I> operator+( difference_type_t<I> n, const reverse_iterator<I>& x);

Effects: Equivalent to: return reverse_iterator<I>(x.current - n);

9.7.1.2.21 iter_move [reverse.iter.iter_move]

friend constexpr rvalue_reference_t<I> iter_move(const reverse_iterator& i) noexcept(see below);

Effects: Equivalent to: return ranges::iter_move(prev(i.current));

Remarks: The expression in noexcept is equivalent to:

   noexcept(ranges::iter_move(declval<I&>())) && noexcept(--declval<I&>()) &&
     is_nothrow_copy_constructible<I>::value

9.7.1.2.22 iter_swap [reverse.iter.iter_swap]

template <IndirectlySwappable<I> I2> friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<I2>& y) noexcept(see below);

Effects: Equivalent to ranges::iter_swap(prev(x.current), prev(y.current)).

Remarks: The expression in noexcept is equivalent to:

  noexcept(ranges::iter_swap(declval<I>(), declval<I>())) && noexcept(--declval<I&>())

9.7.1.2.23 Non-member function make_reverse_iterator() [reverse.iter.make]

template <BidirectionalIterator I> constexpr reverse_iterator<I> make_reverse_iterator(I i);

Returns: reverse_iterator<I>(i).

9.7.2 Insert iterators [iterators.insert]

To make it possible to deal with insertion in the same way as writing into an array, a special kind of iterator adaptors, called insert 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 with result being an insert iterator will insert corresponding elements into the container. This device allows all of the copying algorithms in the library to work in the insert mode instead 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 satisfy OutputIterator. operator* returns the insert iterator itself. The assignment operator=(const T& x) is defined on insert iterators to allow writing into them, it inserts x right 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_iterator inserts elements at the end of a container, front_insert_iterator inserts elements at the beginning of a container, and insert_iterator inserts elements where the iterator points to in a container. back_inserter, front_inserter, and inserter are three functions making the insert iterators out of a container.

9.7.2.1 Class template back_insert_iterator [back.insert.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class Container>
  class back_insert_iterator {
  public:
    using container_type = Container;
    using difference_type = ptrdiff_t;

    constexpr back_insert_iterator();
    explicit back_insert_iterator(Container& x);
    back_insert_iterator&
      operator=(const value_type_t<Container>& value);
    back_insert_iterator&
      operator=(value_type_t<Container>&& value);

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

  private:
    Container* container; // exposition only
  };

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

9.7.2.2 back_insert_iterator operations [back.insert.iter.ops]

9.7.2.2.1 back_insert_iterator constructor [back.insert.iter.cons]

constexpr back_insert_iterator();

Effects: Value-initializes container.

explicit back_insert_iterator(Container& x);

Effects: Initializes container with addressof(x).

9.7.2.2.2 back_insert_iterator::operator= [back.insert.iter.op=]

back_insert_iterator& operator=(const value_type_t<Container>& value);

Effects: Equivalent to container->push_back(value).

Returns: *this.

back_insert_iterator& operator=(value_type_t<Container>&& value);

Effects: Equivalent to container->push_back(std::move(value)).

Returns: *this.

9.7.2.2.3 back_insert_iterator::operator* [back.insert.iter.op*]

back_insert_iterator& operator*();

Returns: *this.

9.7.2.2.4 back_insert_iterator::operator++ [back.insert.iter.op++]

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

Returns: *this.

9.7.2.2.5 back_inserter [back.inserter]

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

Returns: back_insert_iterator<Container>(x).

9.7.2.3 Class template front_insert_iterator [front.insert.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class Container>
  class front_insert_iterator {
  public:
    using container_type = Container;
    using difference_type = ptrdiff_t;

    constexpr front_insert_iterator();
    explicit front_insert_iterator(Container& x);
    front_insert_iterator&
      operator=(const value_type_t<Container>& value);
    front_insert_iterator&
      operator=(value_type_t<Container>&& value);

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

  private:
    Container* container; // exposition only
  };

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

9.7.2.4 front_insert_iterator operations [front.insert.iter.ops]

9.7.2.4.1 front_insert_iterator constructor [front.insert.iter.cons]

constexpr front_insert_iterator();

Effects: Value-initializes container.

explicit front_insert_iterator(Container& x);

Effects: Initializes container with addressof(x).

9.7.2.4.2 front_insert_iterator::operator= [front.insert.iter.op=]

front_insert_iterator& operator=(const value_type_t<Container>& value);

Effects: Equivalent to container->push_front(value).

Returns: *this.

front_insert_iterator& operator=(value_type_t<Container>&& value);

Effects: Equivalent to container->push_front(std::move(value)).

Returns: *this.

9.7.2.4.3 front_insert_iterator::operator* [front.insert.iter.op*]

front_insert_iterator& operator*();

Returns: *this.

9.7.2.4.4 front_insert_iterator::operator++ [front.insert.iter.op++]

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

Returns: *this.

9.7.2.4.5 front_inserter [front.inserter]

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

Returns: front_insert_iterator<Container>(x).

9.7.2.5 Class template insert_iterator [insert.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class Container>
  class insert_iterator {
  public:
    using container_type = Container;
    using difference_type = ptrdiff_t;

    insert_iterator();
    insert_iterator(Container& x, iterator_t<Container> i);
    insert_iterator&
      operator=(const value_type_t<Container>& value);
    insert_iterator&
      operator=(value_type_t<Container>&& value);

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

  private:
    Container* container;       // exposition only
    iterator_t<Container> iter; // exposition only
  };

  template <class Container>
    insert_iterator<Container> inserter(Container& x, iterator_t<Container> i);
}}}}

9.7.2.6 insert_iterator operations [insert.iter.ops]

9.7.2.6.1 insert_iterator constructor [insert.iter.cons]

insert_iterator();

Effects: Value-initializes container and iter.

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

Requires: i is an iterator into x.

Effects: Initializes container with addressof(x) and iter with i.

9.7.2.6.2 insert_iterator::operator= [insert.iter.op=]

insert_iterator& operator=(const value_type_t<Container>& value);

Effects: Equivalent to:

iter = container->insert(iter, value);
++iter;

Returns: *this.

insert_iterator& operator=(value_type_t<Container>&& value);

Effects: Equivalent to:

iter = container->insert(iter, std::move(value));
++iter;

Returns: *this.

9.7.2.6.3 insert_iterator::operator* [insert.iter.op*]

insert_iterator& operator*();

Returns: *this.

9.7.2.6.4 insert_iterator::operator++ [insert.iter.op++]

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

Returns: *this.

9.7.2.6.5 inserter [inserter]

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

Returns: insert_iterator<Container>(x, i).

9.7.3 Move iterators and sentinels [iterators.move]

9.7.3.1 Class template move_iterator [move.iterator]

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 of the value type. Some generic algorithms can be called with move iterators to replace copying with moving.

Example:

list<string> s;
// populate the list s
vector<string> v1(s.begin(), s.end());          // copies strings into v1
vector<string> v2(make_move_iterator(s.begin()),
                  make_move_iterator(s.end())); // moves strings into v2

 — end example ]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <InputIterator I>
  class move_iterator {
  public:
    using iterator_type     = I;
    using difference_type   = difference_type_t<I>;
    using value_type        = value_type_t<I>;
    using iterator_category = input_iterator_tag;
    using reference         = rvalue_reference_t<I>;

    constexpr move_iterator();
    explicit constexpr move_iterator(I i);
    constexpr move_iterator(const move_iterator<ConvertibleTo<I>>& i);
    constexpr move_iterator& operator=(const move_iterator<ConvertibleTo<I>>& i);

    constexpr I base() const;
    constexpr reference operator*() const;

    constexpr move_iterator& operator++();
    constexpr void operator++(int);
    constexpr move_iterator operator++(int)
      requires ForwardIterator<I>;
    constexpr move_iterator& operator--()
      requires BidirectionalIterator<I>;
    constexpr move_iterator operator--(int)
      requires BidirectionalIterator<I>;

    constexpr move_iterator operator+(difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr move_iterator& operator+=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr move_iterator operator-(difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr move_iterator& operator-=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr reference operator[](difference_type n) const
      requires RandomAccessIterator<I>;

    friend constexpr rvalue_reference_t<I> iter_move(const move_iterator& i)
      noexcept(see below);
    template <IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const move_iterator& x, const move_iterator<I2>& y)
        noexcept(see below);

  private:
    I current; // exposition only
  };

  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator==(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator!=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);

  template <class I1, class I2>
      requires SizedSentinel<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const move_iterator<I1>& x,
      const move_iterator<I2>& y);
  template <RandomAccessIterator I>
    constexpr move_iterator<I> operator+(
      difference_type_t<I> n,
      const move_iterator<I>& x);
  template <InputIterator I>
    constexpr move_iterator<I> make_move_iterator(I i);
}}}}

Note: move_iterator does not provide an operator-> because the class member access expression i->m may have different semantics than the expression (*i).m when the expression *i is an rvalue. — end note ]

9.7.3.2 move_iterator operations [move.iter.ops]

9.7.3.2.1 move_iterator constructors [move.iter.op.const]

constexpr move_iterator();

Effects: Constructs a move_iterator, value-initializing current. 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 I.

explicit constexpr move_iterator(I i);

Effects: Constructs a move_iterator, initializing current with i.

constexpr move_iterator(const move_iterator<ConvertibleTo<I>>& i);

Effects: Constructs a move_iterator, initializing current with i.current.

9.7.3.2.2 move_iterator::operator= [move.iter.op=]

constexpr move_iterator& operator=(const move_iterator<ConvertibleTo<I>>& i);

Effects: Assigns i.current to current.

9.7.3.2.3 move_iterator conversion [move.iter.op.conv]

constexpr I base() const;

Returns: current.

9.7.3.2.4 move_iterator::operator* [move.iter.op.star]

constexpr reference operator*() const;

Effects: Equivalent to: return iter_move(current);

9.7.3.2.5 move_iterator::operator++ [move.iter.op.incr]

constexpr move_iterator& operator++();

Effects: Equivalent to ++current.

Returns: *this.

constexpr void operator++(int);

Effects: Equivalent to ++current.

constexpr move_iterator operator++(int) requires ForwardIterator<I>;

Effects: Equivalent to:

move_iterator tmp = *this;
++current;
return tmp;

9.7.3.2.6 move_iterator::operator-- [move.iter.op.decr]

constexpr move_iterator& operator--() requires BidirectionalIterator<I>;

Effects: Equivalent to --current.

Returns: *this.

constexpr move_iterator operator--(int) requires BidirectionalIterator<I>;

Effects: Equivalent to:

move_iterator tmp = *this;
--current;
return tmp;

9.7.3.2.7 move_iterator::operator+ [move.iter.op.+]

constexpr move_iterator operator+(difference_type n) const requires RandomAccessIterator<I>;

Effects: Equivalent to: return move_iterator(current + n);

9.7.3.2.8 move_iterator::operator+= [move.iter.op.+=]

constexpr move_iterator& operator+=(difference_type n) requires RandomAccessIterator<I>;

Effects: Equivalent to current += n.

Returns: *this.

9.7.3.2.9 move_iterator::operator- [move.iter.op.-]

constexpr move_iterator operator-(difference_type n) const requires RandomAccessIterator<I>;

Effects: Equivalent to: return move_iterator(current - n);

9.7.3.2.10 move_iterator::operator-= [move.iter.op.-=]

constexpr move_iterator& operator-=(difference_type n) requires RandomAccessIterator<I>;

Effects: Equivalent to current -= n.

Returns: *this.

9.7.3.2.11 move_iterator::operator[] [move.iter.op.index]

constexpr reference operator[](difference_type n) const requires RandomAccessIterator<I>;

Effects: Equivalent to: return iter_move(current + n);

9.7.3.2.12 move_iterator comparisons [move.iter.op.comp]

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator==( const move_iterator<I1>& x, const move_iterator<I2>& y);

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

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator!=( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return !(x == y);

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return x.current < y.current;

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<=( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return !(y < x);

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return y < x;

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>=( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return !(x < y);.

9.7.3.2.13 move_iterator non-member functions [move.iter.nonmember]

template <class I1, class I2> requires SizedSentinel<I1, I2> constexpr difference_type_t<I2> operator-( const move_iterator<I1>& x, const move_iterator<I2>& y);

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

template <RandomAccessIterator I> constexpr move_iterator<I> operator+( difference_type_t<I> n, const move_iterator<I>& x);

Effects: Equivalent to: return x + n;

friend constexpr rvalue_reference_t<I> iter_move(const move_iterator& i) noexcept(see below);

Effects: Equivalent to: return ranges::iter_move(i.current);

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_move(i.current))

template <IndirectlySwappable<I> I2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<I2>& y) noexcept(see below);

Effects: Equivalent to: ranges::iter_swap(x.current, y.current).

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_swap(x.current, y.current))

template <InputIterator I> constexpr move_iterator<I> make_move_iterator(I i);

Returns: move_iterator<I>(i).

9.7.3.3 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 type I and sentinel type S satisfy Sentinel<S, I>, Sentinel<move_sentinel<S>, move_iterator<I>> is satisfied as well.

Example: A move_if algorithm is easily implemented with copy_if using move_iterator and move_sentinel:

template <InputIterator I, Sentinel<I> S, WeaklyIncrementable O,
          IndirectUnaryPredicate<I> Pred>
  requires IndirectlyMovable<I, O>
void move_if(I first, S last, O out, Pred pred){
  copy_if(move_iterator<I>{first}, move_sentinel<S>{last}, out, pred);
}

 — end example ]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <Semiregular S>
  class move_sentinel {
  public:
    constexpr move_sentinel();
    explicit move_sentinel(S s);
    move_sentinel(const move_sentinel<ConvertibleTo<S>>& s);
    move_sentinel& operator=(const move_sentinel<ConvertibleTo<S>>& s);

    S base() const;

  private:
    S last; // exposition only
  };

  template <class I, Sentinel<I> S>
    constexpr bool operator==(
      const move_iterator<I>& i, const move_sentinel<S>& s);
  template <class I, Sentinel<I> S>
    constexpr bool operator==(
      const move_sentinel<S>& s, const move_iterator<I>& i);
  template <class I, Sentinel<I> S>
    constexpr bool operator!=(
      const move_iterator<I>& i, const move_sentinel<S>& s);
  template <class I, Sentinel<I> S>
    constexpr bool operator!=(
      const move_sentinel<S>& s, const move_iterator<I>& i);

  template <class I, SizedSentinel<I> S>
    constexpr difference_type_t<I> operator-(
      const move_sentinel<S>& s, const move_iterator<I>& i);
  template <class I, SizedSentinel<I> S>
    constexpr difference_type_t<I> operator-(
      const move_iterator<I>& i, const move_sentinel<S>& s);

  template <Semiregular S>
    constexpr move_sentinel<S> make_move_sentinel(S s);
}}}}

9.7.3.4 move_sentinel operations [move.sent.ops]

9.7.3.4.1 move_sentinel constructors [move.sent.op.const]

constexpr move_sentinel();

Effects: Constructs a move_sentinel, value-initializing last. If is_trivially_default_constructible<S>::value is true, then this constructor is a constexpr constructor.

explicit move_sentinel(S s);

Effects: Constructs a move_sentinel, initializing last with s.

move_sentinel(const move_sentinel<ConvertibleTo<S>>& s);

Effects: Constructs a move_sentinel, initializing last with s.last.

9.7.3.4.2 move_sentinel::operator= [move.sent.op=]

move_sentinel& operator=(const move_sentinel<ConvertibleTo<S>>& s);

Effects: Assigns s.last to last.

Returns: *this.

9.7.3.4.3 move_sentinel comparisons [move.sent.op.comp]

template <class I, Sentinel<I> S> constexpr bool operator==( const move_iterator<I>& i, const move_sentinel<S>& s); template <class I, Sentinel<I> S> constexpr bool operator==( const move_sentinel<S>& s, const move_iterator<I>& i);

Effects: Equivalent to: return i.current == s.last;

template <class I, Sentinel<I> S> constexpr bool operator!=( const move_iterator<I>& i, const move_sentinel<S>& s); template <class I, Sentinel<I> S> constexpr bool operator!=( const move_sentinel<S>& s, const move_iterator<I>& i);

Effects: Equivalent to: return !(i == s);

9.7.3.4.4 move_sentinel non-member functions [move.sent.nonmember]

template <class I, SizedSentinel<I> S> constexpr difference_type_t<I> operator-( const move_sentinel<S>& s, const move_iterator<I>& i);

Effects: Equivalent to: return s.last - i.current;

template <class I, SizedSentinel<I> S> constexpr difference_type_t<I> operator-( const move_iterator<I>& i, const move_sentinel<S>& s);

Effects: Equivalent to: return i.current - s.last;

template <Semiregular S> constexpr move_sentinel<S> make_move_sentinel(S s);

Returns: move_sentinel<S>(s).

9.7.4 Common iterators [iterators.common]

Class template common_iterator is an iterator/sentinel adaptor that is capable of representing a non-bounded range of elements (where the types of the iterator and sentinel differ) as a bounded 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: 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:

template <class ForwardIterator>
void fun(ForwardIterator begin, ForwardIterator end);

list<int> s;
// populate the list s
using CI =
  common_iterator<counted_iterator<list<int>::iterator>,
                  default_sentinel>;
// call fun on a range of 10 ints
fun(CI(make_counted_iterator(s.begin(), 10)),
    CI(default_sentinel()));

 — end example ]

9.7.4.1 Class template common_iterator [common.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <Iterator I, Sentinel<I> S>
    requires !Same<I, S>
  class common_iterator {
  public:
    using difference_type = difference_type_t<I>;

    constexpr common_iterator();
    constexpr common_iterator(I i);
    constexpr common_iterator(S s);
    constexpr common_iterator(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);
    common_iterator& operator=(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);

    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);
    common_iterator operator++(int)
      requires ForwardIterator<I>;

    friend rvalue_reference_t<I> iter_move(const common_iterator& i)
      noexcept(see below)
        requires InputIterator<I>;
    template <IndirectlySwappable<I> I2, class S2>
      friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
        noexcept(see below);

  private:
    bool is_sentinel; // exposition only
    I iter;           // exposition only
    S sentinel;       // exposition only
  };

  template <Readable I, class S>
  struct value_type<common_iterator<I, S>> {
    using type = value_type_t<I>;
  };

  template <InputIterator I, class S>
  struct iterator_category<common_iterator<I, S>> {
    using type = input_iterator_tag;
  };

  template <ForwardIterator I, class S>
  struct iterator_category<common_iterator<I, S>> {
    using type = forward_iterator_tag;
  };

  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
  bool operator==(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
    requires EqualityComparableWith<I1, I2>
  bool operator==(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
  bool operator!=(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

  template <class I2, SizedSentinel<I2> I1, SizedSentinel<I2> S1, SizedSentinel<I1> S2>
  difference_type_t<I2> operator-(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
}}}}

9.7.4.2 common_iterator operations [common.iter.ops]

9.7.4.2.1 common_iterator constructors [common.iter.op.const]

constexpr common_iterator();

Effects: Constructs a common_iterator, value-initializing is_sentinel, iter, and sentinel. 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 I.

constexpr common_iterator(I i);

Effects: Constructs a common_iterator, initializing is_sentinel with false, iter with i, and value-initializing sentinel.

constexpr common_iterator(S s);

Effects: Constructs a common_iterator, initializing is_sentinel with true, value-initializing iter, and initializing sentinel with s.

constexpr common_iterator(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);

Effects: Constructs a common_iterator, initializing is_sentinel with u.is_sentinel, iter with u.iter, and sentinel with u.sentinel.

9.7.4.2.2 common_iterator::operator= [common.iter.op=]

common_iterator& operator=(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);

Effects: Assigns u.is_sentinel to is_sentinel, u.iter to iter, and u.sentinel to sentinel.

Returns: *this

9.7.4.2.3 common_iterator::operator* [common.iter.op.star]

decltype(auto) operator*(); decltype(auto) operator*() const requires dereferenceable<const I>;

Requires: !is_sentinel

Effects: Equivalent to: return *iter;

9.7.4.2.4 common_iterator::operator-> [common.iter.op.ref]

decltype(auto) operator->() const requires see below;

Requires: !is_sentinel

Effects: Equivalent to:

  • If I is a pointer type or if the expression i.operator->() is well-formed, return iter;

  • Otherwise, if the expression *iter is a glvalue:

    auto&& tmp = *iter;
    return addressof(tmp);
    
  • Otherwise, return proxy(*iter); where proxy is the exposition-only class:

    class proxy {               // exposition only
      value_type_t<I> keep_;
      proxy(reference_t<I>&& x)
        : keep_(std::move(x)) {}
    public:
      const value_type_t<I>* operator->() const {
        return addressof(keep_);
      }
    };
    

The expression in the requires clause is equivalent to:

Readable<const I> &&
  (requires(const I& i) { i.operator->(); } ||
   is_reference<reference_t<I>>::value ||
   Constructible<value_type_t<I>, reference_t<I>>)

9.7.4.2.5 common_iterator::operator++ [common.iter.op.incr]

common_iterator& operator++();

Requires: !is_sentinel

Effects: Equivalent to ++iter.

Returns: *this.

decltype(auto) operator++(int);

Requires: !is_sentinel.

Effects: Equivalent to: return iter++;

common_iterator operator++(int) requires ForwardIterator<I>;

Requires: !is_sentinel

Effects: Equivalent to:

common_iterator tmp = *this;
++iter;
return tmp;

9.7.4.2.6 common_iterator comparisons [common.iter.op.comp]

template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2> bool operator==( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to:

  return x.is_sentinel ?
    (y.is_sentinel || y.iter == x.sentinel) :
    (!y.is_sentinel || x.iter == y.sentinel);

template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2> requires EqualityComparableWith<I1, I2> bool operator==( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to:

  return x.is_sentinel ?
    (y.is_sentinel || y.iter == x.sentinel) :
    (y.is_sentinel ?
        x.iter == y.sentinel :
        x.iter == y.iter);

template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2> bool operator!=( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to: return !(x == y);

template <class I2, SizedSentinel<I2> I1, SizedSentinel<I2> S1, SizedSentinel<I1> S2> difference_type_t<I2> operator-( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to:

  return x.is_sentinel ?
    (y.is_sentinel ? 0 : x.sentinel - y.iter) :
    (y.is_sentinel ?
         x.iter - y.sentinel :
         x.iter - y.iter);

9.7.4.2.7 iter_move [common.iter.op.iter_move]

friend rvalue_reference_t<I> iter_move(const common_iterator& i) noexcept(see below) requires InputIterator<I>;

Requires: !i.is_sentinel.

Effects: Equivalent to: return ranges::iter_move(i.iter);

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_move(i.iter))

9.7.4.2.8 iter_swap [common.iter.op.iter_swap]

template <IndirectlySwappable<I> I2> friend void iter_swap(const common_iterator& x, const common_iterator<I2>& y) noexcept(see below);

Requires: !x.is_sentinel && !y.is_sentinel.

Effects: Equivalent to ranges::iter_swap(x.iter, y.iter).

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_swap(x.iter, y.iter))

9.7.5 Default sentinels [default.sentinels]

9.7.5.1 Class default_sentinel [default.sent]

namespace std { namespace experimental { namespace ranges { inline namespace v1 { class default_sentinel { }; }}}}

Class default_sentinel is an empty type used to denote the end of a range. It is intended to be used together with iterator types that know the bound of their range (e.g., counted_iterator ([counted.iterator])).

9.7.6 Counted iterators [iterators.counted]

9.7.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 its distance from its starting position. It can be used together with class default_sentinel in 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:

list<string> s;
// populate the list s with at least 10 strings
vector<string> v(make_counted_iterator(s.begin(), 10),
                 default_sentinel()); // copies 10 strings into v

 — end example ]

Two values i1 and i2 of (possibly differing) types counted_iterator<I1> and counted_iterator<I2> refer to elements of the same sequence if and only if next(i1.base(), i1.count()) and next(i2.base(), i2.count()) refer to the same (possibly past-the-end) element.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <Iterator I>
  class counted_iterator {
  public:
    using iterator_type = I;
    using difference_type = difference_type_t<I>;

    constexpr counted_iterator();
    constexpr counted_iterator(I x, difference_type_t<I> n);
    constexpr counted_iterator(const counted_iterator<ConvertibleTo<I>>& i);
    constexpr counted_iterator& operator=(const counted_iterator<ConvertibleTo<I>>& i);

    constexpr I base() const;
    constexpr difference_type_t<I> count() const;
    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 ForwardIterator<I>;
    constexpr counted_iterator& operator--()
      requires BidirectionalIterator<I>;
    constexpr counted_iterator operator--(int)
      requires BidirectionalIterator<I>;

    constexpr counted_iterator  operator+ (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr counted_iterator& operator+=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr counted_iterator  operator- (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr counted_iterator& operator-=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr decltype(auto) operator[](difference_type n) const
      requires RandomAccessIterator<I>;

    friend constexpr rvalue_reference_t<I> iter_move(const counted_iterator& i)
      noexcept(see below)
        requires InputIterator<I>;
    template <IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y)
        noexcept(see below);

  private:
    I current; // exposition only
    difference_type_t<I> cnt; // exposition only
  };

  template <Readable I>
  struct value_type<counted_iterator<I>> {
    using type = value_type_t<I>;
  };

  template <InputIterator I>
  struct iterator_category<counted_iterator<I>> {
    using type = iterator_category_t<I>;
  };

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator==(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
    constexpr bool operator==(
      const counted_iterator<auto>& x, default_sentinel);
    constexpr bool operator==(
      default_sentinel, const counted_iterator<auto>& x);

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator!=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
    constexpr bool operator!=(
      const counted_iterator<auto>& x, default_sentinel y);
    constexpr bool operator!=(
      default_sentinel x, const counted_iterator<auto>& y);

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator<(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator<=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator>(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator>=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I>
    constexpr difference_type_t<I> operator-(
      const counted_iterator<I>& x, default_sentinel y);
  template <class I>
    constexpr difference_type_t<I> operator-(
      default_sentinel x, const counted_iterator<I>& y);

  template <RandomAccessIterator I>
    constexpr counted_iterator<I> operator+(
      difference_type_t<I> n, const counted_iterator<I>& x);

  template <Iterator I>
    constexpr counted_iterator<I> make_counted_iterator(I i, difference_type_t<I> n);
}}}}

9.7.6.2 counted_iterator operations [counted.iter.ops]

9.7.6.2.1 counted_iterator constructors [counted.iter.op.const]

constexpr counted_iterator();

Effects: Constructs a counted_iterator, value-initializing current and cnt. 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 I.

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

Requires: n >= 0

Effects: Constructs a counted_iterator, initializing current with i and cnt with n.

constexpr counted_iterator(const counted_iterator<ConvertibleTo<I>>& i);

Effects: Constructs a counted_iterator, initializing current with i.current and cnt with i.cnt.

9.7.6.2.2 counted_iterator::operator= [counted.iter.op=]

constexpr counted_iterator& operator=(const counted_iterator<ConvertibleTo<I>>& i);

Effects: Assigns i.current to current and i.cnt to cnt.

9.7.6.2.3 counted_iterator conversion [counted.iter.op.conv]

constexpr I base() const;

Returns: current.

9.7.6.2.4 counted_iterator count [counted.iter.op.cnt]

constexpr difference_type_t<I> count() const;

Returns: cnt.

9.7.6.2.5 counted_iterator::operator* [counted.iter.op.star]

constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>;

Effects: Equivalent to: return *current;

9.7.6.2.6 counted_iterator::operator++ [counted.iter.op.incr]

constexpr counted_iterator& operator++();

Requires: cnt > 0

Effects: Equivalent to:

++current;
--cnt;

Returns: *this.

decltype(auto) operator++(int);

Requires: cnt > 0.

Effects: Equivalent to:

--cnt;
try { return current++; }
catch(...) { ++cnt; throw; }

constexpr counted_iterator operator++(int) requires ForwardIterator<I>;

Requires: cnt > 0

Effects: Equivalent to:

counted_iterator tmp = *this;
++*this;
return tmp;

9.7.6.2.7 counted_iterator::operator-- [counted.iter.op.decr]

constexpr counted_iterator& operator--(); requires BidirectionalIterator<I>

Effects: Equivalent to:

--current;
++cnt;

Returns: *this.

constexpr counted_iterator operator--(int) requires BidirectionalIterator<I>;

Effects: Equivalent to:

counted_iterator tmp = *this;
--*this;
return tmp;

9.7.6.2.8 counted_iterator::operator+ [counted.iter.op.+]

constexpr counted_iterator operator+(difference_type n) const requires RandomAccessIterator<I>;

Requires: n <= cnt

Effects: Equivalent to: return counted_iterator(current + n, cnt - n);

9.7.6.2.9 counted_iterator::operator+= [counted.iter.op.+=]

constexpr counted_iterator& operator+=(difference_type n) requires RandomAccessIterator<I>;

Requires: n <= cnt

Effects:

current += n;
cnt -= n;

Returns: *this.

9.7.6.2.10 counted_iterator::operator- [counted.iter.op.-]

constexpr counted_iterator operator-(difference_type n) const requires RandomAccessIterator<I>;

Requires: -n <= cnt

Effects: Equivalent to: return counted_iterator(current - n, cnt + n);

9.7.6.2.11 counted_iterator::operator-= [counted.iter.op.-=]

constexpr counted_iterator& operator-=(difference_type n) requires RandomAccessIterator<I>;

Requires: -n <= cnt

Effects:

current -= n;
cnt += n;

Returns: *this.

9.7.6.2.12 counted_iterator::operator[] [counted.iter.op.index]

constexpr decltype(auto) operator[](difference_type n) const requires RandomAccessIterator<I>;

Requires: n <= cnt

Effects: Equivalent to: return current[n];

9.7.6.2.13 counted_iterator comparisons [counted.iter.op.comp]

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator==( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

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

constexpr bool operator==( const counted_iterator<auto>& x, default_sentinel); constexpr bool operator==( default_sentinel, const counted_iterator<auto>& x);

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

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator!=( const counted_iterator<I1>& x, const counted_iterator<I2>& y); constexpr bool operator!=( const counted_iterator<auto>& x, default_sentinel); constexpr bool operator!=( default_sentinel, const counted_iterator<auto>& x);

Requires: For the first overload, x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return !(x == y);

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator<( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return y.cnt < x.cnt;

Note: The argument order in the Effects element is reversed because cnt counts down, not up.  — end note ]

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator<=( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return !(y < x);

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator>( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return y < x;

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator>=( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return !(x < y);

9.7.6.2.14 counted_iterator non-member functions [counted.iter.nonmember]

template <class I1, class I2> requires Common<I1, I2> constexpr difference_type_t<I2> operator-( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

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

template <class I> constexpr difference_type_t<I> operator-( const counted_iterator<I>& x, default_sentinel y);

Effects: Equivalent to: return -x.cnt;

template <class I> constexpr difference_type_t<I> operator-( default_sentinel x, const counted_iterator<I>& y);

Effects: Equivalent to: return y.cnt;

template <RandomAccessIterator I> constexpr counted_iterator<I> operator+( difference_type_t<I> n, const counted_iterator<I>& x);

Requires: n <= x.cnt.

Effects: Equivalent to: return x + n;

friend constexpr rvalue_reference_t<I> iter_move(const counted_iterator& i) noexcept(see below) requires InputIterator<I>;

Effects: Equivalent to: return ranges::iter_move(i.current);

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_move(i.current))

template <IndirectlySwappable<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(see below);

Effects: Equivalent to ranges::iter_swap(x.current, y.current).

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_swap(x.current, y.current))

template <Iterator I> constexpr counted_iterator<I> make_counted_iterator(I i, difference_type_t<I> n);

Requires: n >= 0.

Returns: counted_iterator<I>(i, n).

9.7.7 Dangling wrapper [dangling.wrappers]

9.7.7.1 Class template dangling [dangling.wrap]

Class template dangling is a wrapper for an object that refers to another object whose lifetime may have ended. It is used by algorithms that accept rvalue ranges and return iterators.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <CopyConstructible T>
  class dangling {
  public:
    constexpr dangling() requires DefaultConstructible<T>;
    constexpr dangling(T t);
    constexpr T get_unsafe() const;
  private:
    T value; // exposition only
  };

  template <Range R>
  using safe_iterator_t =
    conditional_t<is_lvalue_reference<R>::value,
      iterator_t<R>,
      dangling<iterator_t<R>>>;
}}}}

9.7.7.2 dangling operations [dangling.wrap.ops]

9.7.7.2.1 dangling constructors [dangling.wrap.op.const]

constexpr dangling() requires DefaultConstructible<T>;

Effects: Constructs a dangling, value-initializing value.

constexpr dangling(T t);

Effects: Constructs a dangling, initializing value with t.

9.7.7.2.2 dangling::get_unsafe [dangling.wrap.op.get]

constexpr T get_unsafe() const;

Returns: value.

9.7.8 Unreachable sentinel [unreachable.sentinels]

9.7.8.1 Class unreachable [unreachable.sentinel]

Class unreachable is a sentinel type that can be used with any Iterator to denote an infinite range. Comparing an iterator for equality with an object of type unreachable always returns false.

Example:

char* p;
// set p to point to a character buffer containing newlines
char* nl = find(p, unreachable(), '\n');

Provided a newline character really exists in the buffer, the use of unreachable 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 { namespace experimental { namespace ranges { inline namespace v1 {
  class unreachable { };

  template <Iterator I>
    constexpr bool operator==(const I&, unreachable) noexcept;
  template <Iterator I>
    constexpr bool operator==(unreachable, const I&) noexcept;
  template <Iterator I>
    constexpr bool operator!=(const I&, unreachable) noexcept;
  template <Iterator I>
    constexpr bool operator!=(unreachable, const I&) noexcept;
}}}}

9.7.8.2 unreachable operations [unreachable.sentinel.ops]

9.7.8.2.1 operator== [unreachable.sentinel.op==]

template <Iterator I> constexpr bool operator==(const I&, unreachable) noexcept; template <Iterator I> constexpr bool operator==(unreachable, const I&) noexcept;

Returns: false.

9.7.8.2.2 operator!= [unreachable.sentinel.op!=]

template <Iterator I> constexpr bool operator!=(const I& x, unreachable y) noexcept; template <Iterator I> constexpr bool operator!=(unreachable x, const I& y) noexcept;

Returns: true.

9.8 Stream iterators [iterators.stream]

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

Example:

partial_sum(istream_iterator<double, char>(cin),
  istream_iterator<double, char>(),
  ostream_iterator<double, char>(cout, "\n"));

reads a file containing floating point numbers from cin, and prints the partial sums onto cout.  — end example ]

9.8.1 Class template istream_iterator [istream.iterator]

The class template istream_iterator is an input iterator ([iterators.input]) that reads (using operator>>) successive elements from the input stream for which it was constructed. After it is constructed, and every time ++ is used, the iterator reads and stores a value of T. If the iterator fails to read and store a value of T (fail() on the stream returns true), the iterator becomes equal to the end-of-stream iterator value. The constructor with no arguments istream_iterator() always constructs an end-of-stream input iterator object, which is the only legitimate iterator to be used for the end condition. The result of operator* on an end-of-stream iterator is not defined. For any other iterator value a const T& is returned. The result of operator-> on an end-of-stream iterator is not defined. For any other iterator value a const T* is returned. The behavior of a program that applies operator++() to an end-of-stream iterator is undefined. It is impossible to store things into istream iterators.

Two end-of-stream iterators are always equal. An end-of-stream iterator is not equal to a non-end-of-stream iterator. Two non-end-of-stream iterators are equal when they are constructed from the same stream.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class T, class charT = char, class traits = char_traits<charT>,
      class Distance = ptrdiff_t>
  class istream_iterator {
  public:
    typedef input_iterator_tag iterator_category;
    typedef Distance difference_type;
    typedef T value_type;
    typedef const T& reference;
    typedef const T* pointer;
    typedef charT char_type;
    typedef traits traits_type;
    typedef basic_istream<charT, traits> istream_type;
    constexpr istream_iterator();
    constexpr istream_iterator(default_sentinel);
    istream_iterator(istream_type& s);
    istream_iterator(const istream_iterator& x) = default;
    ~istream_iterator() = default;

    const T& operator*() const;
    const T* operator->() const;
    istream_iterator& operator++();
    istream_iterator  operator++(int);
  private:
    basic_istream<charT, traits>* in_stream; // exposition only
    T value;                                 // exposition only
  };

  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);
  template <class T, class charT, class traits, class Distance>
    bool operator==(default_sentinel x,
            const istream_iterator<T, charT, traits, Distance>& y);
  template <class T, class charT, class traits, class Distance>
    bool operator==(const istream_iterator<T, charT, traits, Distance>& x,
            default_sentinel y);
  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);
  template <class T, class charT, class traits, class Distance>
    bool operator!=(default_sentinel x,
            const istream_iterator<T, charT, traits, Distance>& y);
  template <class T, class charT, class traits, class Distance>
    bool operator!=(const istream_iterator<T, charT, traits, Distance>& x,
            default_sentinel y);
}}}}

9.8.1.1 istream_iterator constructors and destructor [istream.iterator.cons]

constexpr istream_iterator(); constexpr istream_iterator(default_sentinel);

Effects: Constructs the end-of-stream iterator. If T is a literal type, then these constructors shall be constexpr constructors.

Postcondition: in_stream == nullptr.

istream_iterator(istream_type& s);

Effects: Initializes in_stream with &s. value may be initialized during construction or the first time it is referenced.

Postcondition: in_stream == &s.

istream_iterator(const istream_iterator& x) = default;

Effects: Constructs a copy of x. If T is a literal type, then this constructor shall be a trivial copy constructor.

Postcondition: in_stream == x.in_stream.

~istream_iterator() = default;

Effects: The iterator is destroyed. If T is a literal type, then this destructor shall be a trivial destructor.

9.8.1.2 istream_iterator operations [istream.iterator.ops]

const T& operator*() const;

Returns: value.

const T* operator->() const;

Effects: Equivalent to: return addressof(operator*()).

istream_iterator& operator++();

Requires: in_stream != nullptr.

Effects: *in_stream >> value.

Returns: *this.

istream_iterator operator++(int);

Requires: in_stream != nullptr.

Effects:

istream_iterator tmp = *this;
*in_stream >> value;
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.

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

Returns: nullptr == y.in_stream.

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

Returns: x.in_stream == nullptr.

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); template <class T, class charT, class traits, class Distance> bool operator!=(default_sentinel x, const istream_iterator<T, charT, traits, Distance>& y); template <class T, class charT, class traits, class Distance> bool operator!=(const istream_iterator<T, charT, traits, Distance>& x, default_sentinel y);

Returns: !(x == y)

9.8.2 Class template ostream_iterator [ostream.iterator]

ostream_iterator writes (using operator<<) successive elements onto the output stream from which it was constructed. If it was constructed with charT* as a constructor argument, this string, called a delimiter string, is written to the stream after every T is written. It is not possible to get a value out of the output iterator. Its only use is as an output iterator in situations like

while (first != last)
  *result++ = *first++;

ostream_iterator is defined as:

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class T, class charT = char, class traits = char_traits<charT>>
  class ostream_iterator {
  public:
    typedef ptrdiff_t difference_type;
    typedef charT char_type;
    typedef traits traits_type;
    typedef basic_ostream<charT, traits> ostream_type;
    constexpr ostream_iterator() noexcept;
    ostream_iterator(ostream_type& s) noexcept;
    ostream_iterator(ostream_type& s, const charT* delimiter) noexcept;
    ostream_iterator(const ostream_iterator& x) noexcept;
    ~ostream_iterator();
    ostream_iterator& operator=(const T& value);

    ostream_iterator& operator*();
    ostream_iterator& operator++();
    ostream_iterator& operator++(int);
  private:
    basic_ostream<charT, traits>* out_stream;  // exposition only
    const charT* delim;                        // exposition only
  };
}}}}

9.8.2.1 ostream_iterator constructors and destructor [ostream.iterator.cons.des]

constexpr ostream_iterator() noexcept;

Effects: Initializes out_stream and delim with nullptr.

ostream_iterator(ostream_type& s) noexcept;

Effects: Initializes out_stream with &s and delim with nullptr.

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

Effects: Initializes out_stream with &s and delim with delimiter.

ostream_iterator(const ostream_iterator& x) noexcept;

Effects: Constructs a copy of x.

~ostream_iterator();

Effects: The iterator is destroyed.

9.8.2.2 ostream_iterator operations [ostream.iterator.ops]

ostream_iterator& operator=(const T& value);

Effects: Equivalent to:

*out_stream << value;
if(delim != nullptr)
  *out_stream << delim;
return *this;

ostream_iterator& operator*();

Returns: *this.

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

Returns: *this.

9.8.3 Class template istreambuf_iterator [istreambuf.iterator]

The class template istreambuf_iterator defines an input iterator ([iterators.input]) that reads successive characters from the streambuf for which it was constructed. operator* provides access to the current input character, if any. Each time operator++ is evaluated, the iterator advances to the next input character. If the end of stream is reached (streambuf_type::sgetc() returns traits::eof()), the iterator becomes equal to the end-of-stream iterator value. The default constructor istreambuf_iterator() and the constructor istreambuf_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 of operator*() on an end-of-stream iterator is undefined. For any other iterator value a char_type value is returned. It is impossible to assign a character via an input iterator.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class charT, class traits = char_traits<charT>>
  class istreambuf_iterator {
  public:
    typedef input_iterator_tag             iterator_category;
    typedef charT                          value_type;
    typedef typename traits::off_type      difference_type;
    typedef charT                          reference;
    typedef unspecified                   pointer;
    typedef charT                          char_type;
    typedef traits                         traits_type;
    typedef typename traits::int_type      int_type;
    typedef basic_streambuf<charT, traits> streambuf_type;
    typedef basic_istream<charT, traits>   istream_type;

    class proxy;                           // exposition only

    constexpr istreambuf_iterator() noexcept;
    constexpr istreambuf_iterator(default_sentinel) 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;
    charT operator*() const;
    istreambuf_iterator& operator++();
    proxy operator++(int);
    bool equal(const istreambuf_iterator& b) const;
  private:
    streambuf_type* sbuf_;                // exposition only
  };

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

9.8.3.1 Class template istreambuf_iterator::proxy [istreambuf.iterator::proxy]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class charT, class traits = char_traits<charT>>
  class istreambuf_iterator<charT, traits>::proxy { // exposition only
    charT keep_;
    basic_streambuf<charT, traits>* sbuf_;
    proxy(charT c, basic_streambuf<charT, traits>* sbuf)
      : keep_(c), sbuf_(sbuf) { }
  public:
    charT operator*() { return keep_; }
  };
}}}}

Class istreambuf_iterator<charT, traits>::proxy is for exposition only. An implementation is permitted to provide equivalent functionality without providing a class with this name. Class istreambuf_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.

9.8.3.2 istreambuf_iterator constructors [istreambuf.iterator.cons]

constexpr istreambuf_iterator() noexcept; constexpr istreambuf_iterator(default_sentinel) noexcept;

Effects: Constructs the end-of-stream iterator.

istreambuf_iterator(basic_istream<charT, traits>& s) noexcept; istreambuf_iterator(basic_streambuf<charT, traits>* s) noexcept;

Effects: Constructs an istreambuf_iterator that uses the basic_streambuf object *(s.rdbuf()), or *s, respectively. Constructs an end-of-stream iterator if s.rdbuf() is null.

istreambuf_iterator(const proxy& p) noexcept;

Effects: Constructs a istreambuf_iterator that uses the basic_streambuf object pointed to by the proxy object's constructor argument p.

9.8.3.3 istreambuf_iterator::operator* [istreambuf.iterator::op*]

charT operator*() const

Returns: The character obtained via the streambuf member sbuf_->sgetc().

9.8.3.4 istreambuf_iterator::operator++ [istreambuf.iterator::op++]

istreambuf_iterator& istreambuf_iterator<charT, traits>::operator++();

Effects: Equivalent to sbuf_->sbumpc().

Returns: *this.

proxy istreambuf_iterator<charT, traits>::operator++(int);

Effects: Equivalent to: return proxy(sbuf_->sbumpc(), sbuf_);

9.8.3.5 istreambuf_iterator::equal [istreambuf.iterator::equal]

bool equal(const istreambuf_iterator& b) const;

Returns: true if and only if both iterators are at end-of-stream, or neither is at end-of-stream, regardless of what streambuf object they use.

9.8.3.6 operator== [istreambuf.iterator::op==]

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

Effects: Equivalent to: return a.equal(b);

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

Effects: Equivalent to: return istreambuf_iterator<charT, traits>{}.equal(b);

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

Effects: Equivalent to: return a.equal(istreambuf_iterator<charT, traits>{});

9.8.3.7 operator!= [istreambuf.iterator::op!=]

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

Effects: Equivalent to: return !(a == b);

9.8.4 Class template ostreambuf_iterator [ostreambuf.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class charT, class traits = char_traits<charT>>
  class ostreambuf_iterator {
  public:
    typedef ptrdiff_t                      difference_type;
    typedef charT                          char_type;
    typedef traits                         traits_type;
    typedef basic_streambuf<charT, traits> streambuf_type;
    typedef basic_ostream<charT, traits>   ostream_type;

    constexpr ostreambuf_iterator() noexcept;
    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_;                // exposition only
  };
}}}}

The class template ostreambuf_iterator writes successive characters onto the output stream from which it was constructed. It is not possible to get a character value out of the output iterator.

9.8.4.1 ostreambuf_iterator constructors [ostreambuf.iter.cons]

constexpr ostreambuf_iterator() noexcept;

Effects: Initializes sbuf_ with nullptr.

ostreambuf_iterator(ostream_type& s) noexcept;

Requires: s.rdbuf() != nullptr.

Effects: Initializes sbuf_ with s.rdbuf().

ostreambuf_iterator(streambuf_type* s) noexcept;

Requires: s != nullptr.

Effects: Initializes sbuf_ with s.

9.8.4.2 ostreambuf_iterator operations [ostreambuf.iter.ops]

ostreambuf_iterator& operator=(charT c);

Requires: sbuf_ != nullptr.

Effects: If failed() yields false, calls sbuf_->sputc(c); otherwise has no effect.

Returns: *this.

ostreambuf_iterator& operator*();

Returns: *this.

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

Returns: *this.

bool failed() const noexcept;

Requires: sbuf_ != nullptr.

Returns: true if in any prior use of member operator=, the call to sbuf_->sputc() returned traits::eof(); or false otherwise.