To implement algorithms only in terms of iterators, it is often necessary to determine the value and difference types that correspond to a particular iterator type. Accordingly, it is required that if Iterator is the type of an iterator, the types
iterator_traits<Iterator>::difference_type iterator_traits<Iterator>::value_type iterator_traits<Iterator>::iterator_category
be defined as the iterator's difference type, value type and iterator category, respectively. In addition, the types
iterator_traits<Iterator>::reference iterator_traits<Iterator>::pointer
shall be defined as the iterator's reference and pointer types, that is, for an iterator object a, the same type as the type of *a and a->, respectively. In the case of an output iterator, the types
iterator_traits<Iterator>::difference_type iterator_traits<Iterator>::value_type iterator_traits<Iterator>::reference iterator_traits<Iterator>::pointer
may be defined as void.
If Iterator has valid ([temp.deduct]) member types difference_type, value_type, pointer, reference, and iterator_category, iterator_traits<Iterator> shall have the following as publicly accessible members:
using difference_type = typename Iterator::difference_type; using value_type = typename Iterator::value_type; using pointer = typename Iterator::pointer; using reference = typename Iterator::reference; using iterator_category = typename Iterator::iterator_category;
Otherwise, iterator_traits<Iterator> shall have no members by any of the above names.
It is specialized for pointers as
namespace std { template<class T> struct iterator_traits<T*> { using difference_type = ptrdiff_t; using value_type = T; using pointer = T*; using reference = T&; using iterator_category = random_access_iterator_tag; }; }
and for pointers to const as
namespace std { template<class T> struct iterator_traits<const T*> { using difference_type = ptrdiff_t; using value_type = T; using pointer = const T*; using reference = const T&; using iterator_category = random_access_iterator_tag; }; }
[ Example: To implement a generic reverse function, a C++ program can do the following:
template <class BidirectionalIterator> void reverse(BidirectionalIterator first, BidirectionalIterator last) { typename iterator_traits<BidirectionalIterator>::difference_type n = distance(first, last); --n; while(n > 0) { typename iterator_traits<BidirectionalIterator>::value_type tmp = *first; *first++ = *--last; *last = tmp; n -= 2; } }
— end example ]
Since only random access iterators provide + and - operators, the library provides two function templates advance and distance. These function templates use + and - for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use ++ to provide linear time implementations.
template <class InputIterator, class Distance>
constexpr void advance(InputIterator& i, Distance n);
template <class InputIterator>
constexpr typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
Effects: If InputIterator meets the requirements of random access iterator, returns (last - first); otherwise, returns the number of increments needed to get from first to last.
Requires: If InputIterator meets the requirements of random access iterator, last shall be reachable from first or first shall be reachable from last; otherwise, last shall be reachable from first.
template <class InputIterator>
constexpr InputIterator next(InputIterator x,
typename iterator_traits<InputIterator>::difference_type n = 1);
template <class BidirectionalIterator>
constexpr BidirectionalIterator prev(BidirectionalIterator x,
typename iterator_traits<BidirectionalIterator>::difference_type n = 1);