9 Iterators library [iterators]

9.6 Iterator primitives [iterator.primitives]

9.6.2 Standard iterator traits [iterator.stdtraits]

To facilitate interoperability between new code using iterators conforming to this document and older code using iterators that conform to the iterator requirements specified in ISO/IEC 14882, three specializations of std::iterator_traits are provided to map the newer iterator categories and associated types to the older ones.

namespace std {
  template <experimental::ranges::Iterator Out>
  struct iterator_traits<Out> {
    using difference_type   = experimental::ranges::difference_type_t<Out>;
    using value_type        = see below;
    using reference         = see below;
    using pointer           = see below;
    using iterator_category = std::output_iterator_tag;
  };
}

The nested type value_type is computed as follows:

  • If Out::value_type is valid and denotes a type, then std::iterator_traits<Out>::value_type is Out::value_type.

  • Otherwise, std::iterator_traits<Out>::value_type is void.

The nested type reference is computed as follows:

  • If Out::reference is valid and denotes a type, then std::iterator_traits<Out>::reference is Out::reference.

  • Otherwise, std::iterator_traits<Out>::reference is void.

The nested type pointer is computed as follows:

  • If Out::pointer is valid and denotes a type, then std::iterator_traits<Out>::pointer is Out::pointer.

  • Otherwise, std::iterator_traits<Out>::pointer is void.

namespace std {
  template <experimental::ranges::InputIterator In>
  struct iterator_traits<In> { };

  template <experimental::ranges::InputIterator In>
    requires experimental::ranges::Sentinel<In, In>
  struct iterator_traits<In> {
    using difference_type   = experimental::ranges::difference_type_t<In>;
    using value_type        = experimental::ranges::value_type_t<In>;
    using reference         = see below;
    using pointer           = see below;
    using iterator_category = see below;
  };
}

The nested type reference is computed as follows:

  • If In::reference is valid and denotes a type, then std::iterator_traits<In>::reference is In::reference.

  • Otherwise, std::iterator_traits<In>::reference is experimental::ranges::reference_t<In>.

The nested type pointer is computed as follows:

  • If In::pointer is valid and denotes a type, then std::iterator_traits<In>::pointer is In::pointer.

  • Otherwise, std::iterator_traits<In>::pointer is experimental::ranges::iterator_traits<In>::pointer.

Let type C be experimental::ranges::iterator_category_t<In>. The nested type std::iterator_traits<In>::iterator_category is computed as follows:

  • If C is the same as or inherits from std::input_iterator_tag or std::output_iterator_tag, std::iterator_traits<In>::iterator_category is C.

  • Otherwise, if experimental::ranges::reference_t<In> is not a reference type, std::iterator_traits<In>::iterator_category is std::input_iterator_tag.

  • Otherwise, if C is the same as or inherits from experimental::ranges::random_access_iterator_tag, std::iterator_traits<In>::iterator_category is std::random_access_iterator_tag.

  • Otherwise, if C is the same as or inherits from experimental::ranges::bidirectional_iterator_tag, std::iterator_traits<In>::iterator_category is std::bidirectional_iterator_tag.

  • Otherwise, if C is the same as or inherits from experimental::ranges::forward_iterator_tag, std::iterator_traits<In>::iterator_category is std::forward_iterator_tag.

  • Otherwise, std::iterator_traits<In>::iterator_category is std::input_iterator_tag.

Note: Some implementations may find it necessary to add additional constraints to these partial specializations to prevent them from being considered for types that conform to the iterator requirements specified in ISO/IEC 14882. — end note ]