156 lines
12 KiB
Markdown
156 lines
12 KiB
Markdown
[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> 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> 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*]
|