23 Iterators library [iterators]

23.4 Iterator primitives [iterator.primitives]

23.4.3 Range iterator operations [range.iter.ops]

The library includes the function templates ranges​::​advance, ranges​::​distance, ranges​::​next, and ranges​::​prev to manipulate iterators.
These operations adapt to the set of operators provided by each iterator category to provide the most efficient implementation possible for a concrete iterator type.
[Example
:
ranges​::​advance uses the + operator to move a random_­access_­iterator forward n steps in constant time.
For an iterator type that does not model random_­access_­iterator, ranges​::​advance instead performs n individual increments with the ++ operator.
— end example
]
The function templates defined in this subclause are not found by argument-dependent name lookup ([basic.lookup.argdep]).
When found by unqualified ([basic.lookup.unqual]) name lookup for the postfix-expression in a function call ([expr.call]), they inhibit argument-dependent name lookup.
[Example
:
void foo() {
    using namespace std::ranges;
    std::vector<int> vec{1,2,3};
    distance(begin(vec), end(vec));     // #1
}
The function call expression at #1 invokes std​::​ranges​::​distance, not std​::​distance, despite that (a) the iterator type returned from begin(vec) and end(vec) may be associated with namespace std and (b) std​::​distance is more specialized ([temp.func.order]) than std​::​ranges​::​distance since the former requires its first two parameters to have the same type.
— end example
]
The number and order of deducible template parameters for the function templates defined in this subclause is unspecified, except where explicitly stated otherwise.

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

template<input_­or_­output_­iterator I> constexpr void ranges::advance(I& i, iter_difference_t<I> n);
Preconditions: If I does not model bidirectional_­iterator, n is not negative.
Effects:
  • If I models random_­access_­iterator, equivalent to i += n.
  • Otherwise, if n is non-negative, increments i by n.
  • Otherwise, decrements i by -n.
template<input_­or_­output_­iterator I, sentinel_­for<I> S> constexpr void ranges::advance(I& i, S bound);
Preconditions: [i, bound) denotes a range.
Effects:
  • If I and S model assignable_­from<I&, S>, equivalent to i = std​::​move(bound).
  • Otherwise, if S and I model sized_­sentinel_­for<S, I>, equivalent to ranges​::​advance(i, bound - i).
  • Otherwise, while bool(i != bound) is true, increments i.
template<input_­or_­output_­iterator I, sentinel_­for<I> S> constexpr iter_difference_t<I> ranges::advance(I& i, iter_difference_t<I> n, S bound);
Preconditions: If n > 0, [i, bound) denotes a range.
If n == 0, [i, bound) or [bound, i) denotes a range.
If n < 0, [bound, i) denotes a range, I models bidirectional_­iterator, and I and S model same_­as<I, S>.
Effects:
  • If S and I model sized_­sentinel_­for<S, I>:
    • If ​, equivalent to ranges​::​advance(i, bound).
    • Otherwise, equivalent to ranges​::​advance(i, n).
  • Otherwise,
    • if n is non-negative, while bool(i != bound) is true, increments i but at most n times.
    • Otherwise, while bool(i != bound) is true, decrements i but at most -n times.
Returns: n - M, where M is the difference between the ending and starting positions of i.

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

template<input_­or_­output_­iterator I, sentinel_­for<I> S> constexpr iter_difference_t<I> ranges::distance(I first, S last);
Preconditions: [first, last) denotes a range, or [last, first) denotes a range and S and I model same_­as<S, I> && sized_­sentinel_­for<S, I>.
Effects: If S and I model sized_­sentinel_­for<S, I>, returns (last - first); otherwise, returns the number of increments needed to get from first to last.
template<range R> constexpr range_difference_t<R> ranges::distance(R&& r);
Effects: If R models sized_­range, equivalent to:
return static_cast<range_difference_t<R>>(ranges::size(r));     // [range.prim.size]
Otherwise, equivalent to:
return ranges::distance(ranges::begin(r), ranges::end(r));      // [range.access]

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

template<input_­or_­output_­iterator I> constexpr I ranges::next(I x);
Effects: Equivalent to: ++x; return x;
template<input_­or_­output_­iterator I> constexpr I ranges::next(I x, iter_difference_t<I> n);
Effects: Equivalent to: ranges​::​advance(x, n); return x;
template<input_­or_­output_­iterator I, sentinel_­for<I> S> constexpr I ranges::next(I x, S bound);
Effects: Equivalent to: ranges​::​advance(x, bound); return x;
template<input_­or_­output_­iterator I, sentinel_­for<I> S> constexpr I ranges::next(I x, iter_difference_t<I> n, S bound);
Effects: Equivalent to: ranges​::​advance(x, n, bound); return x;

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

template<bidirectional_­iterator I> constexpr I ranges::prev(I x);
Effects: Equivalent to: --x; return x;
template<bidirectional_­iterator I> constexpr I ranges::prev(I x, iter_difference_t<I> n);
Effects: Equivalent to: ranges​::​advance(x, -n); return x;
template<bidirectional_­iterator I> constexpr I ranges::prev(I x, iter_difference_t<I> n, I bound);
Effects: Equivalent to: ranges​::​advance(x, -n, bound); return x;