[iterator.traits]

# 24 Iterators library [[iterators]](./#iterators)

## 24.3 Iterator requirements [[iterator.requirements]](iterator.requirements#iterator.traits)

### 24.3.2 Associated types [[iterator.assoc.types]](iterator.assoc.types#iterator.traits)

#### 24.3.2.3 Iterator traits [iterator.traits]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L908)

To implement algorithms only in terms of iterators, it is sometimes necessary to
determine the iterator category that corresponds to a particular iterator type[.](#1.sentence-1)

Accordingly, it is required that ifI is the type of an iterator,
the type

[ð](#lib:iterator_category,iterator_traits)

iterator_traits<I>::iterator_category be defined as the iterator's iterator category[.](#1.sentence-2)

In addition, the types

[ð](#lib:pointer,iterator_traits)

iterator_traits<I>::pointer
iterator_traits<I>::reference shall be defined as the iterator's pointer and reference types;
that is, for an
iterator object a of class type,
the same type asdecltype(a.operator->()) anddecltype(*a),
respectively[.](#1.sentence-3)

The typeiterator_traits<I>​::​pointer shall be void for an iterator of class type I that does not support operator->[.](#1.sentence-4)

Additionally, in the case of an output iterator, the typesiterator_traits<I>::value_type
iterator_traits<I>::difference_type
iterator_traits<I>::reference may be defined as void[.](#1.sentence-5)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L948)

The definitions in this subclause make use of the following
exposition-only concepts:template<class I>concept [*cpp17-iterator*](#concept:cpp17-iterator "24.3.2.3 Iterator traits [iterator.traits]") =requires(I i) {{ *i } -> [*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]"); { ++i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I&>; { *i++ } -> [*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]"); } && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<I>;

template<class I>concept [*cpp17-input-iterator*](#concept:cpp17-input-iterator "24.3.2.3 Iterator traits [iterator.traits]") =[*cpp17-iterator*](#concept:cpp17-iterator "24.3.2.3 Iterator traits [iterator.traits]")<I> && [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<I> && requires(I i) {typename incrementable_traits<I>::difference_type; typename indirectly_readable_traits<I>::value_type; typename common_reference_t<iter_reference_t<I>&&, typename indirectly_readable_traits<I>::value_type&>; typename common_reference_t<decltype(*i++)&&, typename indirectly_readable_traits<I>::value_type&>; requires [signed_integral](concepts.arithmetic#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<typename incrementable_traits<I>::difference_type>; };

template<class I>concept [*cpp17-forward-iterator*](#concept:cpp17-forward-iterator "24.3.2.3 Iterator traits [iterator.traits]") =[*cpp17-input-iterator*](#concept:cpp17-input-iterator "24.3.2.3 Iterator traits [iterator.traits]")<I> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<I> && is_reference_v<iter_reference_t<I>> &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<iter_reference_t<I>>, typename indirectly_readable_traits<I>::value_type> &&requires(I i) {{ i++ } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<const I&>; { *i++ } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<iter_reference_t<I>>; };

template<class I>concept [*cpp17-bidirectional-iterator*](#concept:cpp17-bidirectional-iterator "24.3.2.3 Iterator traits [iterator.traits]") =[*cpp17-forward-iterator*](#concept:cpp17-forward-iterator "24.3.2.3 Iterator traits [iterator.traits]")<I> && requires(I i) {{ --i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I&>; { i-- } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<const I&>; { *i-- } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<iter_reference_t<I>>; };

template<class I>concept [*cpp17-random-access-iterator*](#concept:cpp17-random-access-iterator "24.3.2.3 Iterator traits [iterator.traits]") =[*cpp17-bidirectional-iterator*](#concept:cpp17-bidirectional-iterator "24.3.2.3 Iterator traits [iterator.traits]")<I> && [totally_ordered](concept.totallyordered#concept:totally_ordered "18.5.5 Concept totally_­ordered [concept.totallyordered]")<I> &&requires(I i, typename incrementable_traits<I>::difference_type n) {{ i += n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I&>; { i -= n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I&>; { i + n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I>; { n + i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I>; { i - n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<I>; { i - i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<decltype(n)>; { i[n] } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iter_reference_t<I>>; };

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L1005)

The members of a specialization iterator_traits<I> generated from theiterator_traits primary template are computed as follows:

- [(3.1)](#3.1)

If I has valid ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction")) member
types difference_type, value_type,reference, and iterator_category,
theniterator_traits<I> has the following publicly accessible members:using iterator_category = typename I::iterator_category;using value_type = typename I::value_type;using difference_type = typename I::difference_type;using pointer = *see below*;using reference = typename I::reference;
   If the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") I​::​pointer is valid and
denotes a type, then iterator_traits<I>​::​pointer names that type;
otherwise, it names void[.](#3.1.sentence-2)

- [(3.2)](#3.2)

Otherwise, if I satisfies the exposition-only concept[*cpp17-input-iterator*](#concept:cpp17-input-iterator "24.3.2.3 Iterator traits [iterator.traits]"),iterator_traits<I> has the following
publicly accessible members:using iterator_category = *see below*;using value_type = typename indirectly_readable_traits<I>::value_type;using difference_type = typename incrementable_traits<I>::difference_type;using pointer = *see below*;using reference = *see below*;
  * [(3.2.1)](#3.2.1)

      If the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") I​::​pointer is valid and denotes a type,pointer names that type[.](#3.2.1.sentence-1)
      Otherwise, ifdecltype(​declval<I&>().operator->()) is well-formed, thenpointer names that type[.](#3.2.1.sentence-2)
      Otherwise, pointer names void[.](#3.2.1.sentence-3)

  * [(3.2.2)](#3.2.2)

      If the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") I​::​reference is valid and denotes a
type, reference names that type[.](#3.2.2.sentence-1)
      Otherwise, reference names iter_reference_t<I>[.](#3.2.2.sentence-2)

  * [(3.2.3)](#3.2.3)

      If the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") I​::​iterator_category is valid and
denotes a type, iterator_category names that type[.](#3.2.3.sentence-1)
      Otherwise, iterator_category names:
    +
          [(3.2.3.1)](#3.2.3.1)
random_access_iterator_tag ifI satisfies [*cpp17-random-access-iterator*](#concept:cpp17-random-access-iterator "24.3.2.3 Iterator traits [iterator.traits]"),
or otherwise

    +
          [(3.2.3.2)](#3.2.3.2)
bidirectional_iterator_tag ifI satisfies [*cpp17-bidirectional-iterator*](#concept:cpp17-bidirectional-iterator "24.3.2.3 Iterator traits [iterator.traits]"),
or otherwise

    +
          [(3.2.3.3)](#3.2.3.3)
forward_iterator_tag ifI satisfies [*cpp17-forward-iterator*](#concept:cpp17-forward-iterator "24.3.2.3 Iterator traits [iterator.traits]"),
or otherwise

    +
          [(3.2.3.4)](#3.2.3.4)
input_iterator_tag[.](#3.2.3.sentence-2)

- [(3.3)](#3.3)

Otherwise, if I satisfies the exposition-only concept[*cpp17-iterator*](#concept:cpp17-iterator "24.3.2.3 Iterator traits [iterator.traits]"), then iterator_traits<I> has the following publicly accessible
members:using iterator_category = output_iterator_tag;using value_type = void;using difference_type = *see below*;using pointer = void;using reference = void;
   If the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")incrementable_traits<I>​::​difference_type is valid and denotes a type,
then difference_type names that type; otherwise, it names void[.](#3.3.sentence-2)

- [(3.4)](#3.4)

Otherwise, iterator_traits<I> has no members by any of the above names[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L1094)

Explicit or partial specializations of iterator_traits may
have a member type iterator_concept that is used to indicate
conformance to the iterator concepts ([[iterator.concepts]](iterator.concepts "24.3.4 Iterator concepts"))[.](#4.sentence-1)

[*Example [1](#example-1)*:

To indicate conformance to the [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]") concept
but a lack of conformance to
the *Cpp17InputIterator* requirements ([[input.iterators]](input.iterators "24.3.5.3 Input iterators")),
an iterator_traits specialization might haveiterator_concept denote input_iterator_tag but not define iterator_category[.](#4.sentence-2)

â *end example*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L1107)

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

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L1124)

[*Example [2](#example-2)*:

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

â *end example*]
