std::iterator_traits - cppreference.com (original) (raw)
| Defined in header | | | | ---------------------------------------------------------------------------- | | ------------------ | | template< class Iter > struct iterator_traits; | | | | template< class T > struct iterator_traits<T*>; | | | | template< class T > struct iterator_traits<const T*>; | | (removed in C++20) |
std::iterator_traits
is the type trait class that provides uniform interface to the properties of LegacyIterator types. This makes it possible to implement algorithms only in terms of iterators.
The template can be specialized for user-defined iterators so that the information about the iterator can be retrieved even if the type does not provide the usual typedefs.
User specializations may define the nested type iterator_concept to one of iterator category tags, to indicate conformance to the iterator concepts. | (since C++20) |
---|
Contents
[edit] Template parameters
Iter | - | the iterator type to retrieve properties for |
---|
[edit] Member types
Nested type | Definition |
---|---|
difference_type | Iter::difference_type |
value_type | Iter::value_type |
pointer | Iter::pointer |
reference | Iter::reference |
iterator_category | Iter::iterator_category |
If Iter does not have any of the five nested types above, then this template has no members by any of those names (std::iterator_traits is SFINAE-friendly). | (since C++17)(until C++20) |
---|---|
If Iter does not have pointer, but has all four remaining nested types, then these four nested types are declared as follows: Nested type Definition difference_type Iter::difference_type value_type Iter::value_type pointer void reference Iter::reference iterator_category Iter::iterator_category Otherwise, if Iter satisfies the exposition-only concept __LegacyInputIterator, the nested types are declared as follows: Nested type Definition difference_type std::incrementable_traits<Iter>::difference_type value_type std::indirectly_readable_traits<Iter>::value_type pointer Iter::pointer if valid. Otherwise decltype(std::declval<Iter&>().operator->()) if valid. Otherwise void. reference Iter::reference if valid. Otherwise std::iter_reference_t<Iter>. iterator_category Iter::iterator_category if valid. Otherwise, std::random_access_iterator_tag if Iter satisfies __LegacyRandomAccessIterator. Otherwise, std::bidirectional_iterator_tag if Iter satisfies __LegacyBidirectionalIterator. Otherwise, std::forward_iterator_tag if Iter satisfies __LegacyForwardIterator. Otherwise, std::input_iterator_tag. Otherwise, if Iter satisfies the exposition-only concept __LegacyIterator, the nested types are declared as follows: Nested type Definition difference_type std::incrementable_traits<Iter>::difference_type if valid. Otherwise void. value_type void pointer void reference void iterator_category std::output_iterator_tag Otherwise, this template has no members by any of those names (std::iterator_traits is SFINAE-friendly). | (since C++20) |
[edit] Specializations
This type trait may be specialized for user-provided types that may be used as iterators. The standard library provides partial specializations for pointer types T*
, which makes it possible to use all iterator-based algorithms with raw pointers.
The standard library also provides partial specializations for some standard iterator adaptors. | (since C++20) |
---|
[edit] T*
specialization nested types
Nested type | Definition |
---|---|
difference_type | std::ptrdiff_t |
value_type | T(until C++20)std::remove_cv_t<T>(since C++20) |
pointer | T* |
reference | T& |
iterator_category | std::random_access_iterator_tag |
iterator_concept (since C++20) | std::contiguous_iterator_tag |
[edit] Specializations for library types
[edit] Example
Shows a general-purpose std::reverse() implementation for bidirectional iterators.
#include #include #include #include template void my_reverse(BidirIt first, BidirIt last) { typename std::iterator_traits::difference_type n = std::distance(first, last); for (--n; n > 0; n -= 2) { typename std::iterator_traits::value_type tmp = *first; *first++ = *--last; *last = tmp; } } int main() { std::vector v{1, 2, 3, 4, 5}; my_reverse(v.begin(), v.end()); for (int n : v) std::cout << n << ' '; std::cout << '\n'; std::list l{1, 2, 3, 4, 5}; my_reverse(l.begin(), l.end()); for (int n : l) std::cout << n << ' '; std::cout << '\n'; int a[]{1, 2, 3, 4, 5}; my_reverse(a, a + std::size(a)); for (int n : a) std::cout << n << ' '; std::cout << '\n'; // std::istreambuf_iterator i1(std::cin), i2; // my_reverse(i1, i2); // compilation error: i1, i2 are input iterators }
Output:
5 4 3 2 1 5 4 3 2 1 5 4 3 2 1