[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::iterator_category be defined as the iterator's iterator category[.](#1.sentence-2) In addition, the types [🔗](#lib:pointer,iterator_traits) iterator_traits::pointer iterator_traits::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​::​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::value_type iterator_traits::difference_type iterator_traits::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:templateconcept [*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  synopsis [iterator.synopsis]"); { ++i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { *i++ } -> [*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]"); } && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"); templateconcept [*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]") && [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]") && requires(I i) {typename incrementable_traits::difference_type; typename indirectly_readable_traits::value_type; typename common_reference_t&&, typename indirectly_readable_traits::value_type&>; typename common_reference_t::value_type&>; requires [signed_integral](concepts.arithmetic#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")::difference_type>; }; templateconcept [*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]") && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") && is_reference_v> &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")>, typename indirectly_readable_traits::value_type> &&requires(I i) {{ i++ } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); { *i++ } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")>; }; templateconcept [*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]") && requires(I i) {{ --i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { i-- } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); { *i-- } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")>; }; templateconcept [*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]") && [totally_ordered](concept.totallyordered#concept:totally_ordered "18.5.5 Concept totally_­ordered [concept.totallyordered]") &&requires(I i, typename incrementable_traits::difference_type n) {{ i += n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { i -= n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { i + n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { n + i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { i - n } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { i - i } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { i[n] } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")>; }; [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L1005) The members of a specialization iterator_traits 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 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​::​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 has the following publicly accessible members:using iterator_category = *see below*;using value_type = typename indirectly_readable_traits::value_type;using difference_type = typename incrementable_traits::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().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[.](#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 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​::​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 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 {templaterequires is_object_vstruct iterator_traits {using iterator_concept = contiguous_iterator_tag; using iterator_category = random_access_iterator_tag; using value_type = remove_cv_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:templatevoid reverse(BI first, BI last) {typename iterator_traits::difference_type n = distance(first, last); --n; while (n > 0) {typename iterator_traits::value_type tmp = *first; *first++ = *--last; *last = tmp; n -= 2; }} — *end example*]