[iterator.assoc.types] (original) (raw)
23 Iterators library [iterators]
23.3 Iterator requirements [iterator.requirements]
23.3.2 Associated types [iterator.assoc.types]
23.3.2.1 Incrementable traits [incrementable.traits]
To implement algorithms only in terms of incrementable types, it is often necessary to determine the difference type that corresponds to a particular incrementable type.
Accordingly, it is required that if WI is the name of a type that models theweakly_incrementable concept ([iterator.concept.winc]), the type
iter_difference_t
be defined as the incrementable type's difference type.
namespace std { template struct incrementable_traits { };
template requires is_object_v struct incrementable_traits<T*> { using difference_type = ptrdiff_t; };
template struct incrementable_traits : incrementable_traits { };
template requires requires { typename T::difference_type; } struct incrementable_traits { using difference_type = typename T::difference_type; };
template requires (!requires { typename T::difference_type; } && requires(const T& a, const T& b) { { a - b } -> integral; }) struct incrementable_traits { using difference_type = make_signed_t<decltype(declval() - declval())>; };
template using iter_difference_t = see below; }
Let be remove_cvref_t<I>.
The type iter_difference_t<I> denotes
- incrementable_traits<>::difference_typeif iterator_traits<> names a specialization generated from the primary template, and
- iterator_traits<>::difference_type otherwise.
Users may specialize incrementable_traits on program-defined types.
23.3.2.2 Indirectly readable traits [readable.traits]
To implement algorithms only in terms of indirectly readable types, it is often necessary to determine the value type that corresponds to a particular indirectly readable type.
Accordingly, it is required that if R is the name of a type that models the indirectly_readable concept ([iterator.concept.readable]), the type
iter_value_t
be defined as the indirectly readable type's value type.
template struct cond-value-type { };
template
requires is_object_v
struct cond-value-type {
using value_type = remove_cv_t;
};
template struct indirectly_readable_traits { };
template struct indirectly_readable_traits<T*> : cond-value-type { };
template requires is_array_v struct indirectly_readable_traits { using value_type = remove_cv_t<remove_extent_t>; };
template struct indirectly_readable_traits : indirectly_readable_traits { };
template requires requires { typename T::value_type; } struct indirectly_readable_traits : cond-value-type { };
template requires requires { typename T::element_type; } struct indirectly_readable_traits : cond-value-type { };
template using iter_value_t = see below;
Let be remove_cvref_t<I>.
The type iter_value_t<I> denotes
- indirectly_readable_traits<>::value_typeif iterator_traits<> names a specialization generated from the primary template, and
- iterator_traits<>::value_type otherwise.
Class template indirectly_readable_traits may be specialized on program-defined types.
[ Note
:
Some legacy output iterators define a nested type named value_typethat is an alias for void.
These types are not indirectly_readableand have no associated value types.
— end note
]
[ Note
:
Smart pointers like shared_ptr<int> are indirectly_readable and have an associated value type, but a smart pointer like shared_ptr<void>is not indirectly_readable and has no associated value type.
— end note
]
23.3.2.3 Iterator traits [iterator.traits]
To implement algorithms only in terms of iterators, it is sometimes necessary to determine the iterator category that corresponds to a particular iterator type.
Accordingly, it is required that ifIis the type of an iterator, the type
iterator_traits::iterator_category
be defined as the iterator's iterator category.
In addition, the types
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.
The typeiterator_traits<I>::pointershall be voidfor an iterator of class type Ithat does not support operator->.
Additionally, in the case of an output iterator, the types
iterator_traits::value_type iterator_traits::difference_type iterator_traits::reference
may be defined as void.
The definitions in this subclause make use of the following exposition-only concepts:
template concept cpp17-iterator = copyable && requires(I i) { { *i } -> can-reference; { ++i } -> same_as<I&>; { *i++ } -> can-reference; };
template concept cpp17-input-iterator = cpp17-iterator && equality_comparable && requires(I i) { typename incrementable_traits::difference_type; typename indirectly_readable_traits::value_type; typename common_reference_t<iter_reference_t&&, typename indirectly_readable_traits::value_type&>; typename common_reference_t<decltype(*i++)&&, typename indirectly_readable_traits::value_type&>; requires signed_integral<typename incrementable_traits::difference_type>; };
template concept cpp17-forward-iterator = cpp17-input-iterator && constructible_from && is_lvalue_reference_v<iter_reference_t> && same_as<remove_cvref_t<iter_reference_t>, typename indirectly_readable_traits::value_type> && requires(I i) { { i++ } -> convertible_to<const I&>; { *i++ } -> same_as<iter_reference_t>; };
template concept cpp17-bidirectional-iterator = cpp17-forward-iterator && requires(I i) { { --i } -> same_as<I&>; { i-- } -> convertible_to<const I&>; { *i-- } -> same_as<iter_reference_t>; };
template concept cpp17-random-access-iterator = cpp17-bidirectional-iterator && totally_ordered && requires(I i, typename incrementable_traits::difference_type n) { { i += n } -> same_as<I&>; { i -= n } -> same_as<I&>; { i + n } -> same_as; { n + i } -> same_as; { i - n } -> same_as; { i - i } -> same_as<decltype(n)>; { i[n] } -> convertible_to<iter_reference_t>; };
The members of a specialization iterator_traits<I> generated from theiterator_traits primary template are computed as follows:
- If I has valid ([temp.deduct]) 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 I::pointer is valid and denotes a type, then iterator_traits<I>::pointer names that type; otherwise, it names void. - Otherwise, if I satisfies the exposition-only conceptcpp17-input-iterator,iterator_traits<I> 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;- If the qualified-id I::pointer is valid and denotes a type,pointer names that type. Otherwise, ifdecltype(declval<I&>().operator->()) is well-formed, thenpointer names that type. Otherwise, pointernames void.
- If the qualified-id I::reference is valid and denotes a type, reference names that type. Otherwise, referencenames iter_reference_t<I>.
- If the qualified-id I::iterator_category is valid and denotes a type, iterator_category names that type. Otherwise, iterator_category names:
* random_access_iterator_tagifI satisfies cpp17-random-access-iterator, or otherwise
* bidirectional_iterator_tag ifI satisfies cpp17-bidirectional-iterator, or otherwise
* forward_iterator_tag ifI satisfies cpp17-forward-iterator, or otherwise
* input_iterator_tag.
- Otherwise, if I satisfies the exposition-only conceptcpp17-iterator, 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 incrementable_traits<I>::difference_type is valid and denotes a type, then difference_type names that type; otherwise, it names void. - Otherwise, iterator_traits<I>has no members by any of the above names.
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_traits is specialized for pointers as
namespace std { template requires is_object_v struct iterator_traits<T*> { 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&; }; }
[ Example
:
To implement a genericreversefunction, a C++ program can do the following:
template void 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
]