To simplify the task of defining iterators, the library provides several classes and functions:
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 ]
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 ]
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.
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.
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;