Standard library header <iterator>

From cppreference.com
< cpp‎ | header
 
 
 

This header is part of the iterator library.

Concepts

Iterator concepts
specifies that a type is readable by applying operator *
(concept)
specifies that a value can be written to an iterator's referenced object
(concept)
specifies that a Semiregular type can be incremented with pre- and post-increment operators
(concept)
specifies that the increment operation on a WeaklyIncrementable type is equality-preserving and that the type is EqualityComparable
(concept)
specifies that objects of a type can be incremented and dereferenced
(concept)
specifies a type is a sentinel for an Iterator type
(concept)
specifies that the - operator can be applied to an iterator and a sentinel to calculate their difference in constant time
(concept)
specifies that a type is an input iterator, that is, its referenced values can be read and it can be both pre- and post-incremented
(concept)
specifies that a type is an output iterator for a given value type, that is, values of that type can be written to it and it can be both pre- and post-incremented
(concept)
specifies that an InputIterator is a forward iterator, supporting equality comparison and multi-pass
(concept)
specifies that a ForwardIterator is a bidirectional interator, supporting movement backwards
(concept)
specifies that a BidirectionalIterator is a random-access iterator, supporting advancement in constant time and subscripting
(concept)
specifies that a RandomAccessIterator is a contiguous iterator, referring to elements that are contiguous in memory
(concept)
Indirect callable concepts
specifies that a callable type can be invoked with the result of dereferencing a Readable type
(concept)
specifies that a callable type, when invoked with the result of dereferencing a Readable type, satisfies Predicate
(concept)
specifies that a callable type, when invoked with the result of dereferencing two Readable types, satisfies Predicate
(concept)
specifies that a callable type, when invoked with the result of dereferencing two Readable types, satisfies StrictWeakOrder
(concept)
Common algorithm requirements
specifies that values may be moved from a Readable type to a Writable type
(concept)
specifies that values may be moved from a Readable type to a Writable type and that the move may be performed via an intermediate object
(concept)
specifies that values may be copied from a Readable type to a Writable type
(concept)
specifies that values may be copied from a Readable type to a Writable type and that the copy may be performed via an intermediate object
(concept)
specifies that the values referenced by two Readable types can be swapped
(concept)
specifies that the values referenced by two Readable types can be compared
(concept)
specifies the common requirements of algorithms that reorder elements in place
(concept)
specifies the requirements of algorithms that merge sorted sequences into an output sequence by copying elements
(concept)
specifies the common requirements of algorithms that permute sequences into ordered sequences
(concept)

Classes

Algorithm utilities
computes the result of invoking a callable object on the result of dereferencing some set of Readable types
(alias template)
helper template for specifying the constraints on algorithms that accept projections
(class template)
Associated types
computes the difference type of a WeaklyIncrementable type
(class template)
computes the value type of a Readable type
(class template)
computes the associate types of an iterator
(alias template)
Primitives
provides uniform interface to the properties of an iterator
(class template)
empty class types used to indicate iterator categories
(class)
(deprecated in C++17)
base class to ease the definition of required types for simple iterators
(class template)
Adaptors
iterator adaptor for reverse-order traversal
(class template)
iterator adaptor which dereferences to an rvalue reference
(class template)
sentinel adaptor for use with std::move_iterator
(class template)
adapts an iterator type and its sentinel into a common iterator type
(class template)
default sentinel for use with iterators that know the bound of their range
(class)
iterator adaptor that tracks the distance to the end of the range
(class template)
sentinel that always compares unequal to any WeaklyIncrementable type
(class)
iterator adaptor for insertion at the end of a container
(class template)
iterator adaptor for insertion at the front of a container
(class template)
iterator adaptor for insertion into a container
(class template)
Stream Iterators
input iterator that reads from std::basic_istream
(class template)
output iterator that writes to std::basic_ostream
(class template)
input iterator that reads from std::basic_streambuf
(class template)
output iterator that writes to std::basic_streambuf
(class template)

Customization point objects

Defined in namespace std::ranges
casts the result of dereferencing an object to its associated rvalue reference type
(customization point object)
swap the values referenced by two dereferenceable objects
(customization point object)

Functions

Adaptors
creates a std::reverse_iterator of type inferred from the argument
(function template)
creates a std::move_iterator of type inferred from the argument
(function template)
creates a std::front_insert_iterator of type inferred from the argument
(function template)
creates a std::back_insert_iterator of type inferred from the argument
(function template)
creates a std::insert_iterator of type inferred from the argument
(function template)
Non-member operators
compares the underlying iterators
(function template)
advances the iterator
(function template)
computes the distance between two iterator adaptors
(function template)
compares the underlying iterators
(function template)
advances the iterator
(function template)
computes the distance between two iterator adaptors
(function template)
compares two istream_iterators
(function template)
compares two istreambuf_iterators
(function template)
Operations
advances an iterator by given distance
(function template)
returns the distance between two iterators
(function template)
(C++11)
increment an iterator
(function template)
(C++11)
decrement an iterator
(function template)
advances an iterator by given distance or to a given bound
(niebloid)
returns the distance between an iterator and a sentinel, or between the beginning and end of a range
(niebloid)
increment an iterator by a given distance or to a bound
(niebloid)
decrement an iterator by a given distance or to a bound
(niebloid)
Range access
(C++11)(C++14)
returns an iterator to the beginning of a container or array
(function template)
(C++11)(C++14)
returns an iterator to the end of a container or array
(function template)
returns a reverse iterator to a container or array
(function template)
(C++14)
returns a reverse end iterator for a container or array
(function template)
(C++17)(C++20)
returns the size of a container or array
(function template)
(C++17)
checks whether the container is empty
(function template)
(C++17)
obtains the pointer to the underlying array
(function template)

Synopsis

#include <concepts>
 
namespace std {
  template<class T> using __with_reference = T&;// exposition only
  template<class T> concept __Referenceable     // exposition only
    = requires { typename __with_reference<T>; };
  template<class T> concept __Dereferenceable   // exposition only
    = requires(T& t) {
      { *t } -> __Referenceable; // not required to be equality-preserving
    };
 
  // associated types
  // incrementable traits
  template<class> struct incrementable_traits;
  template<class T>
    using iter_difference_t = /* see definition */;
 
  // readable traits
  template<class> struct readable_traits;
  template<class T>
    using iter_value_t = /* see definition */;
 
  // iterator traits
  template<class I> struct iterator_traits;
  template<class T> struct iterator_traits<T*>;
 
  template<__Dereferenceable T>
    using iter_reference_t = decltype(*declval<T&>());
 
  namespace ranges {
    // customization points
    inline namespace /* unspecified */ {
      // ranges​::​iter_­move
      inline constexpr /* unspecified */ iter_move = /* unspecified */;
 
      // ranges​::​iter_­swap
      inline constexpr /* unspecified */ iter_swap = /* unspecified */;
    }
  }
 
  template<__Dereferenceable T>
    requires requires(T& t) {
      { ranges::iter_move(t) } -> __Referenceable;
    }
  using iter_rvalue_reference_t
    = decltype(ranges::iter_move(declval<T&>()));
 
  // iterator concepts
  // concept Readable
  template<class In>
    concept Readable = /* see definition */;
 
  template<Readable T>
    using iter_common_reference_t =
      common_reference_t<iter_reference_t<T>, iter_value_t<T>&>;
 
  // concept Writable
  template<class Out, class T>
    concept Writable = /* see definition */;
 
  // concept WeaklyIncrementable
  template<class I>
    concept WeaklyIncrementable = /* see definition */;
 
  // concept Incrementable
  template<class I>
    concept Incrementable = /* see definition */;
 
  // concept Iterator
  template<class I>
    concept Iterator = /* see definition */;
 
  // concept Sentinel
  template<class S, class I>
    concept Sentinel = /* see definition */;
 
  // concept SizedSentinel
  template<class S, class I>
    inline constexpr bool disable_sized_sentinel = false;
 
  template<class S, class I>
    concept SizedSentinel = /* see definition */;
 
  // concept InputIterator
  template<class I>
    concept InputIterator = /* see definition */;
 
  // concept OutputIterator
  template<class I, class T>
    concept OutputIterator = /* see definition */;
 
  // concept ForwardIterator
  template<class I>
    concept ForwardIterator = /* see definition */;
 
  // concept BidirectionalIterator
  template<class I>
    concept BidirectionalIterator = /* see definition */;
 
  // concept RandomAccessIterator
  template<class I>
    concept RandomAccessIterator = /* see definition */;
 
  // concept ContiguousIterator
  template<class I>
    concept ContiguousIterator = /* see definition */;
 
  // indirect callable requirements
  // indirect callables
  template<class F, class I>
    concept IndirectUnaryInvocable = /* see definition */;
 
  template<class F, class I>
    concept IndirectRegularUnaryInvocable = /* see definition */;
 
  template<class F, class I>
    concept IndirectUnaryPredicate = /* see definition */;
 
  template<class F, class I1, class I2 = I1>
    concept IndirectRelation = /* see definition */;
 
  template<class F, class I1, class I2 = I1>
    concept IndirectStrictWeakOrder = /* see definition */;
 
  template<class F, class... Is>
    requires (Readable<Is> && ...) && Invocable<F, iter_reference_t<Is>...>
      using indirect_result_t = invoke_result_t<F, iter_reference_t<Is>...>;
 
  // projected
  template<Readable I, IndirectRegularUnaryInvocable<I> Proj>
    struct projected;
 
  template<WeaklyIncrementable I, class Proj>
    struct incrementable_traits<projected<I, Proj>>;
 
  // common algorithm requirements
  // concept IndirectlyMovable
  template<class In, class Out>
    concept IndirectlyMovable = /* see definition */;
 
  template<class In, class Out>
    concept IndirectlyMovableStorable = /* see definition */;
 
  // concept IndirectlyCopyable
  template<class In, class Out>
    concept IndirectlyCopyable = /* see definition */;
 
  template<class In, class Out>
    concept IndirectlyCopyableStorable = /* see definition */;
 
  // concept IndirectlySwappable
  template<class I1, class I2 = I1>
    concept IndirectlySwappable = /* see definition */;
 
  // concept IndirectlyComparable
  template<class I1, class I2, class R, class P1 = identity, class P2 = identity>
    concept IndirectlyComparable = /* see definition */;
 
  // concept Permutable
  template<class I>
    concept Permutable = /* see definition */;
 
  // concept Mergeable
  template<class I1, class I2, class Out,
      class R = ranges::less, class P1 = identity, class P2 = identity>
    concept Mergeable = /* see definition */;
 
  // concept Sortable
  template<class I, class R = ranges::less, class P = identity>
    concept Sortable = /* see definition */;
 
  // primitives
  // iterator tags
  struct input_iterator_tag { };
  struct output_iterator_tag { };
  struct forward_iterator_tag: public input_iterator_tag { };
  struct bidirectional_iterator_tag: public forward_iterator_tag { };
  struct random_access_iterator_tag: public bidirectional_iterator_tag { };
  struct contiguous_iterator_tag: public random_access_iterator_tag { };
 
  // iterator operations
  template<class InputIter, class Distance>
    constexpr void
      advance(InputIter& i, Distance n);
  template<class InputIter>
    constexpr typename iterator_traits<InputIter>::difference_type
      distance(InputIter first, InputIter last);
  template<class InputIter>
    constexpr InputIter
      next(InputIter x,
           typename iterator_traits<InputIter>::difference_type n = 1);
  template<class BidirIter>
    constexpr BidirIter
      prev(BidirIter x,
           typename iterator_traits<BidirIter>::difference_type n = 1);
 
  // range iterator operations
  namespace ranges {
    // ranges​::​advance
    template<Iterator I>
      constexpr void advance(I& i, iter_difference_t<I> n);
    template<Iterator I, Sentinel<I> S>
      constexpr void advance(I& i, S bound);
    template<Iterator I, Sentinel<I> S>
      constexpr iter_difference_t<I> advance(I& i, iter_difference_t<I> n, S bound);
 
    // ranges​::​distance
    template<Iterator I, Sentinel<I> S>
      constexpr iter_difference_t<I> distance(I first, S last);
    template<Range R>
      constexpr iter_difference_t<iterator_t<R>> distance(R&& r);
 
    // ranges​::​next
    template<Iterator I>
      constexpr I next(I x);
    template<Iterator I>
      constexpr I next(I x, iter_difference_t<I> n);
    template<Iterator I, Sentinel<I> S>
      constexpr I next(I x, S bound);
    template<Iterator I, Sentinel<I> S>
      constexpr I next(I x, iter_difference_t<I> n, S bound);
 
    // ranges​::​prev
    template<BidirectionalIterator I>
      constexpr I prev(I x);
    template<BidirectionalIterator I>
      constexpr I prev(I x, iter_difference_t<I> n);
    template<BidirectionalIterator I>
      constexpr I prev(I x, iter_difference_t<I> n, I bound);
  }
 
  // predefined iterators and sentinels
  // reverse iterators
  template<class Iter> class reverse_iterator;
 
  template<class Iter1, class Iter2>
    constexpr bool operator==(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator!=(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator<(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator>(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator<=(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator>=(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y);
 
  template<class Iter1, class Iter2>
    constexpr auto operator-(
      const reverse_iterator<Iter1>& x,
      const reverse_iterator<Iter2>& y) -> decltype(y.base() - x.base());
  template<class Iter>
    constexpr reverse_iterator<Iter>
      operator+(
    typename reverse_iterator<Iter>::difference_type n,
    const reverse_iterator<Iter>& x);
 
  template<class Iter>
    constexpr reverse_iterator<Iter> make_reverse_iterator(Iter i);
 
  template<class Iter1, class Iter2>
      requires (!SizedSentinel<Iter1, Iter2>)
    inline constexpr bool disable_sized_sentinel<reverse_iterator<Iter1>,
                                                 reverse_iterator<Iter2>> = true;
 
  // insert iterators
  template<class Container> class back_insert_iterator;
  template<class Container>
    constexpr back_insert_iterator<Container> back_inserter(Container& x);
 
  template<class Container> class front_insert_iterator;
  template<class Container>
    constexpr front_insert_iterator<Container> front_inserter(Container& x);
 
  template<class Container> class insert_iterator;
  template<class Container>
    constexpr insert_iterator<Container>
      inserter(Container& x, ranges::iterator_t<Container> i);
 
  // move iterators and sentinels
  template<class Iter> class move_iterator;
 
  template<class Iter1, class Iter2>
    constexpr bool operator==(
      const move_iterator<Iter1>& x, const move_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator!=(
      const move_iterator<Iter1>& x, const move_iterator<Iter2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator<(
      const move_iterator<Iter1>& x, const move_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator>(
      const move_iterator<Iter1>& x, const move_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator<=(
      const move_iterator<Iter1>& x, const move_iterator<Iter2>& y);
  template<class Iter1, class Iter2>
    constexpr bool operator>=(
      const move_iterator<Iter1>& x, const move_iterator<Iter2>& y);
 
  template<class Iter1, class Iter2>
    constexpr auto operator-(
    const move_iterator<Iter1>& x,
    const move_iterator<Iter2>& y) -> decltype(x.base() - y.base());
  template<class Iter>
    constexpr move_iterator<Iter> operator+(
      typename move_iterator<Iter>::difference_type n, const move_iterator<Iter>& x);
 
  template<class Iter>
    constexpr move_iterator<Iter> make_move_iterator(Iter i);
 
  template<Semiregular S> class move_sentinel;
 
  // common iterators
  template<Iterator I, Sentinel<I> S>
    requires (!Same<I, S>)
      class common_iterator;
 
  template<class I, class S>
    struct incrementable_traits<common_iterator<I, S>>;
 
  template<InputIterator I, class S>
    struct iterator_traits<common_iterator<I, S>>;
 
  // default sentinels
  struct default_sentinel_t;
  inline constexpr default_sentinel_t default_sentinel{};
 
  // counted iterators
  template<Iterator I> class counted_iterator;
 
  template<class I>
    struct incrementable_traits<counted_iterator<I>>;
 
  template<InputIterator I>
    struct iterator_traits<counted_iterator<I>>;
 
  // unreachable sentinels
  struct unreachable_sentinel_t;
  inline constexpr unreachable_sentinel_t unreachable_sentinel{};
 
  // stream iterators
  template<class T, class CharT = char, class Traits = char_traits<CharT>,
           class Distance = ptrdiff_t>
  class istream_iterator;
  template<class T, class CharT, class Traits, class Distance>
    bool operator==(const istream_iterator<T, CharT, Traits, Distance>& x,
            const istream_iterator<T, CharT, Traits, Distance>& y);
  template<class T, class CharT, class Traits, class Distance>
    bool operator!=(const istream_iterator<T, CharT, Traits, Distance>& x,
            const istream_iterator<T, CharT, Traits, Distance>& y);
 
  template<class T, class CharT = char, class Traits = char_traits<CharT>>
      class ostream_iterator;
 
  template<class CharT, class Traits = char_traits<CharT>>
    class istreambuf_iterator;
  template<class CharT, class Traits>
    bool operator==(const istreambuf_iterator<CharT, Traits>& a,
            const istreambuf_iterator<CharT, Traits>& b);
  template<class CharT, class Traits>
    bool operator!=(const istreambuf_iterator<CharT, Traits>& a,
            const istreambuf_iterator<CharT, Traits>& b);
 
  template<class CharT, class Traits = char_traits<CharT>>
    class ostreambuf_iterator;
 
  // range access
  template<class C> constexpr auto begin(C& c) -> decltype(c.begin());
  template<class C> constexpr auto begin(const C& c) -> decltype(c.begin());
  template<class C> constexpr auto end(C& c) -> decltype(c.end());
  template<class C> constexpr auto end(const C& c) -> decltype(c.end());
  template<class T, size_t N> constexpr T* begin(T (&a)[N]) noexcept;
  template<class T, size_t N> constexpr T* end(T (&a)[N]) noexcept;
  template<class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c)))
    -> decltype(std::begin(c));
  template<class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c)))
    -> decltype(std::end(c));
  template<class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin());
  template<class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());
  template<class C> constexpr auto rend(C& c) -> decltype(c.rend());
  template<class C> constexpr auto rend(const C& c) -> decltype(c.rend());
  template<class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&a)[N]);
  template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&a)[N]);
  template<class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);
  template<class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il);
  template<class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));
  template<class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));
 
  template<class C> constexpr auto size(const C& c) -> decltype(c.size());
  template<class T, size_t N> constexpr size_t size(const T (&a)[N]) noexcept;
  template<class C> constexpr auto ssize(const C& c)
    -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;
  template<class T, ptrdiff_t N> constexpr ptrdiff_t ssize(const T (&a)[N]) noexcept;
  template<class C> [[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty());
  template<class T, size_t N> [[nodiscard]] constexpr bool empty(const T (&a)[N]) noexcept;
  template<class E> [[nodiscard]] constexpr bool empty(initializer_list<E> il) noexcept;
  template<class C> constexpr auto data(C& c) -> decltype(c.data());
  template<class C> constexpr auto data(const C& c) -> decltype(c.data());
  template<class T, size_t N> constexpr T* data(T (&a)[N]) noexcept;
  template<class E> constexpr const E* data(initializer_list<E> il) noexcept;
}

Concept Readable

template<class In>
    concept Readable =
        requires {
            typename iter_value_t<In>;
            typename iter_reference_t<In>;
            typename iter_rvalue_reference_t<In>;
        } &&
        CommonReference<iter_reference_t<In>&&, iter_value_t<In>&> &&
        CommonReference<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&&> &&
        CommonReference<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>;

Concept Writable

template<class Out, class T>
    concept Writable =
        requires(Out&& o, T&& t) {
            *o = std::forward<T>(t); // not required to be equality-preserving
            *std::forward<Out>(o) =
                std::forward<T>(t); // not required to be equality-preserving
            const_cast<const iter_reference_t<Out>&&>(*o) =
                std::forward<T>(t); // not required to be equality-preserving
            const_cast<const iter_reference_t<Out>&&>(*std::forward<Out>(o)) =
                std::forward<T>(t); // not required to be equality-preserving
    };

Concept WeaklyIncrementable

template<class I>
    concept WeaklyIncrementable =
        Semiregular<I> &&
        requires(I i) {
            typename iter_difference_t<I>;
            requires SignedIntegral<iter_difference_t<I>>;
            { ++i } -> Same<I&>; // not required to be equality-preserving
            i++; // not required to be equality-preserving
        };

Concept Incrementable

template<class I>
    concept Incrementable =
        Regular<I> &&
        WeaklyIncrementable<I> &&
        requires(I i) {
            { i++ } -> Same<I>;
        };

Concept Iterator

template<class I>
    concept Iterator =
        requires(I i) {
            { *i } -> __Referenceable;
        } &&
        WeaklyIncrementable<I>;

Concept Sentinel

template<class S, class I>
    concept Sentinel =
        Semiregular<S> &&
        Iterator<I> &&
        __WeaklyEqualityComparableWith<S, I>; // See [concept.equalitycomparable]

Concept SizedSentinel

template<class S, class I>
    concept SizedSentinel =
        Sentinel<S, I> &&
        !disable_sized_sentinel<remove_cv_t<S>, remove_cv_t<I>> &&
        requires(const I& i, const S& s) {
            { s - i } -> Same<iter_difference_t<I>>;
            { i - s } -> Same<iter_difference_t<I>>;
        };

Concept InputIterator

template<class I>
    concept InputIterator =
        Iterator<I> &&
        Readable<I> &&
        requires { typename ITER_CONCEPT(I); } &&
        DerivedFrom<ITER_CONCEPT(I), input_iterator_tag>;

Concept OutputIterator

template<class I, class T>
    concept OutputIterator =
        Iterator<I> &&
        Writable<I, T> &&
        requires(I i, T&& t) {
            *i++ = std::forward<T>(t); // not required to be equality-preserving
        };

Concept ForwardIterator

template<class I>
    concept ForwardIterator =
        InputIterator<I> &&
        DerivedFrom<ITER_CONCEPT(I), forward_iterator_tag> &&
        Incrementable<I> &&
        Sentinel<I, I>;

Concept BidirectionalIterator

template<class I>
    concept BidirectionalIterator =
        ForwardIterator<I> &&
        DerivedFrom<ITER_CONCEPT(I), bidirectional_iterator_tag> &&
        requires(I i) {
            { --i } -> Same<I&>;
            { i-- } -> Same<I>;
        };

Concept RandomAccessIterator

template<class I>
    concept RandomAccessIterator =
        BidirectionalIterator<I> &&
        DerivedFrom<ITER_CONCEPT(I), random_access_iterator_tag> &&
        StrictTotallyOrdered<I> &&
        SizedSentinel<I, I> &&
        requires(I i, const I j, const iter_difference_t<I> n) {
            { i += n } -> Same<I&>;
            { j +  n } -> Same<I>;
            { n +  j } -> Same<I>;
            { i -= n } -> Same<I&>;
            { j -  n } -> Same<I>;
            {  j[n]  } -> Same<iter_reference_t<I>>;
        };

Concept ContiguousIterator

template<class I>
    concept ContiguousIterator =
        RandomAccessIterator<I> &&
        DerivedFrom<ITER_CONCEPT(I), contiguous_iterator_tag> &&
        is_lvalue_reference_v<iter_reference_t<I>> &&
        Same<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>>;

Concept IndirectUnaryInvocable

template<class F, class I>
    concept IndirectUnaryInvocable =
        Readable<I> &&
        CopyConstructible<F> &&
        Invocable<F&, iter_value_t<I>&> &&
        Invocable<F&, iter_reference_t<I>> &&
        Invocable<F&, iter_common_reference_t<I>> &&
        CommonReference<
            invoke_result_t<F&, iter_value_t<I>&>,
            invoke_result_t<F&, iter_reference_t<I>>>;

Concept IndirectRegularUnaryInvocable

template<class F, class I>
    concept IndirectRegularUnaryInvocable =
        Readable<I> &&
        CopyConstructible<F> &&
        RegularInvocable<F&, iter_value_t<I>&> &&
        RegularInvocable<F&, iter_reference_t<I>> &&
        RegularInvocable<F&, iter_common_reference_t<I>> &&
        CommonReference<
            invoke_result_t<F&, iter_value_t<I>&>,
            invoke_result_t<F&, iter_reference_t<I>>>;

Concept IndirectUnaryPredicate

template<class F, class I>
    concept IndirectUnaryPredicate =
        Readable<I> &&
        CopyConstructible<F> &&
        Predicate<F&, iter_value_t<I>&> &&
        Predicate<F&, iter_reference_t<I>> &&
        Predicate<F&, iter_common_reference_t<I>>;

Concept IndirectRelation

template<class F, class I1, class I2 = I1>
    concept IndirectRelation =
        Readable<I1> && Readable<I2> &&
        CopyConstructible<F> &&
        Relation<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
        Relation<F&, iter_value_t<I1>&, iter_reference_t<I2>> &&
        Relation<F&, iter_reference_t<I1>, iter_value_t<I2>&> &&
        Relation<F&, iter_reference_t<I1>, iter_reference_t<I2>> &&
        Relation<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

Concept IndirectStrictWeakOrder

template<class F, class I1, class I2 = I1>
    concept IndirectStrictWeakOrder =
        Readable<I1> && Readable<I2> &&
        CopyConstructible<F> &&
        StrictWeakOrder<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
        StrictWeakOrder<F&, iter_value_t<I1>&, iter_reference_t<I2>> &&
        StrictWeakOrder<F&, iter_reference_t<I1>, iter_value_t<I2>&> &&
        StrictWeakOrder<F&, iter_reference_t<I1>, iter_reference_t<I2>> &&
        StrictWeakOrder<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;

Concept IndirectlyMovable

template<class In, class Out>
    concept IndirectlyMovable =
        Readable<In> &&
        Writable<Out, iter_rvalue_reference_t<In>>;

Concept IndirectlyMovableStorable

template<class In, class Out>
    concept IndirectlyMovableStorable =
        IndirectlyMovable<In, Out> &&
        Writable<Out, iter_value_t<In>> &&
        Movable<iter_value_t<In>> &&
        Constructible<iter_value_t<In>, iter_rvalue_reference_t<In>> &&
        Assignable<iter_value_t<In>&, iter_rvalue_reference_t<In>>;

Concept IndirectlyCopyable

template<class In, class Out>
    concept IndirectlyCopyable =
        Readable<In> &&
        Writable<Out, iter_reference_t<In>>;

Concept IndirectlyCopyableStorable

template<class In, class Out>
    concept IndirectlyCopyableStorable =
        IndirectlyCopyable<In, Out> &&
        Writable<Out, const iter_value_t<In>&> &&
        Copyable<iter_value_t<In>> &&
        Constructible<iter_value_t<In>, iter_reference_t<In>> &&
        Assignable<iter_value_t<In>&, iter_reference_t<In>>;

Concept IndirectlySwappable

template<class I1, class I2 = I1>
    concept IndirectlySwappable =
        Readable<I1> && Readable<I2> &&
        requires(I1& i1, I2& i2) {
            ranges::iter_swap(i1, i1);
            ranges::iter_swap(i2, i2);
            ranges::iter_swap(i1, i2);
            ranges::iter_swap(i2, i1);
        };

Concept IndirectlyComparable

template<class I1, class I2, class R, class P1 = identity,
         class P2 = identity>
    concept IndirectlyComparable =
        IndirectRelation<R, projected<I1, P1>, projected<I2, P2>>;

Concept Permutable

template<class I>
    concept Permutable =
        ForwardIterator<I> &&
        IndirectlyMovableStorable<I, I> &&
        IndirectlySwappable<I, I>;

Concept Mergeable

template<class I1, class I2, class Out, class R = ranges::less,
         class P1 = identity, class P2 = identity>
    concept Mergeable =
        InputIterator<I1> &&
        InputIterator<I2> &&
        WeaklyIncrementable<Out> &&
        IndirectlyCopyable<I1, Out> &&
        IndirectlyCopyable<I2, Out> &&
        IndirectStrictWeakOrder<R, projected<I1, P1>, projected<I2, P2>>;

Concept Sortable

template<class I, class R = ranges::less, class P = identity>
    concept Sortable =
        Permutable<I> &&
        IndirectStrictWeakOrder<R, projected<I, P>>;

Class template std::incrementable_traits

template<class> struct incrementable_traits { };
 
template<class T>
    requires is_object_v<T>
struct incrementable_traits<T*> {
    using difference_type = ptrdiff_t;
};
 
template<class I>
struct incrementable_traits<const I>
    : incrementable_traits<I> { };
 
template<class T> requires requires { typename T::difference_type; }
struct incrementable_traits<T> {
    using difference_type = typename T::difference_type;
};
 
template<class T>
    requires (!requires { typename T::difference_type; } &&
               requires(const T& a, const T& b) { { a - b } -> Integral; })
struct incrementable_traits<T> {
    using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>;
};

Class template std::readable_traits

template<class> struct __cond_value_type { };   // exposition only
template<class T>
    requires is_object_v<T>
struct __cond_value_type {
    using value_type = remove_cv_t<T>;
};
 
template<class> struct readable_traits { };
 
template<class T>
struct readable_traits<T*>
    : __cond_value_type<T> { };
 
template<class I>
    requires is_array_v<I>
struct readable_traits<I> {
    using value_type = remove_cv_t<remove_extent_t<I>>;
};
 
template<class I>
struct readable_traits<const I>
    : readable_traits<I> { };
 
template<class T>
    requires requires { typename T::value_type; }
struct readable_traits<T>
    : __cond_value_type<typename T::value_type> { };
 
template<class T>
    requires requires { typename T::element_type; }
struct readable_traits<T>
    : __cond_value_type<typename T::element_type> { };

Class template std::projected

template<Readable I, IndirectRegularUnaryInvocable<I> Proj>
struct projected {
    using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>;
    indirect_result_t<Proj&, I> operator*() const; // not defined
};
 
template<WeaklyIncrementable I, class Proj>
struct incrementable_traits<projected<I, Proj>> {
    using difference_type = iter_difference_t<I>;
};

Class template std::iterator_traits

template<class It> struct iterator_traits {
    using difference_type   = /* see definition */;
    using value_typet       = /* see definition */;
    using pointer           = /* see definition */;
    using reference         = /* see definition */;
    using iterator_category = /* see definition */;
};
 
template<class T>
    requires is_object_v<T>
struct iterator_traits<T*> {
    using difference_type   = ptrdiff_t;
    using value_type        = remove_cv_t<T>;
    using pointer           = T*;
    using reference         = T&;
    using iterator_concept  = contiguous_iterator_tag;
    using iterator_category = random_access_iterator_tag;
};

Iterator tags

struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag: public input_iterator_tag { };
struct bidirectional_iterator_tag: public forward_iterator_tag { };
struct random_access_iterator_tag: public bidirectional_iterator_tag { };
struct contiguous_iterator_tag: public random_access_iterator_tag { };

Class template std::reverse_iterator

template <class It>
class reverse_iterator {
public:
    using iterator_type     = It;
    using iterator_concept  = /* see definition */;
    using iterator_category = /* see definition */;
    using value_type        = iter_value_t<It>;
    using difference_type   = iter_difference_t<It>;
    using pointer           = typename iterator_traits<It>::pointer;
    using reference         = iter_reference_t<It>::reference;
 
    constexpr reverse_iterator();
    constexpr explicit reverse_iterator(It x);
    template <class U> constexpr reverse_iterator(const reverse_iterator<U>& u);
    template <class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);
 
    constexpr iterator_type base() const;
    constexpr reference operator*() const;
    constexpr pointer   operator->() const;
 
    constexpr reverse_iterator& operator++();
    constexpr reverse_iterator  operator++(int);
    constexpr reverse_iterator& operator--();
    constexpr reverse_iterator  operator--(int);
 
    constexpr reverse_iterator  operator+ (difference_type n) const;
    constexpr reverse_iterator& operator+=(difference_type n);
    constexpr reverse_iterator  operator- (difference_type n) const;
    constexpr reverse_iterator& operator-=(difference_type n);
 
    constexpr /*unspecified*/ operator[](difference_type n) const;
 
    friend constexpr iter_rvalue_reference_t<It>
        iter_move(const reverse_iterator& i) noexcept(/* see definition */);
    template<IndirectlySwappable<It> It2>
        friend constexpr void
            iter_swap(const reverse_iterator& x,
                      const reverse_iterator<It2>& y) noexcept(/* see definition */);
 
protected:
    It current;
};

Class template std::back_insert_iterator

template<class Container>
class back_insert_iterator {
protected:
    Container* container = nullptr;
 
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using container_type    = Container;
 
    constexpr back_insert_iterator() noexcept = default;
    explicit constexpr back_insert_iterator(Container& x);
    constexpr back_insert_iterator& operator=(const typename Container::value_type& value);
    constexpr back_insert_iterator& operator=(typename Container::value_type&& value);
 
    constexpr back_insert_iterator& operator*();
    constexpr back_insert_iterator& operator++();
    constexpr back_insert_iterator operator++(int);
};

Class template std::front_insert_iterator

template<class Container>
class front_insert_iterator {
protected:
    Container* container = nullptr;
 
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using container_type    = Container;
 
    constexpr front_insert_iterator(Container& x) noexcept = default;
    explicit constexpr front_insert_iterator(Container& x);
    constexpr front_insert_iterator& operator=(const typename Container::value_type& val);
    constexpr front_insert_iterator& operator=(typename Container::value_type&& val);
 
    constexpr front_insert_iterator& operator*();
    constexpr front_insert_iterator& operator++();
    constexpr front_insert_iterator operator++(int);
};

Class template std::insert_iterator

template<class Container>
class insert_iterator {
protected:
    Container* container = nullptr;
    ranges::iterator_t<Container> iter = ranges::iterator_t<Container>();
 
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using container_type    = Container;
 
    insert_iterator() = default;
    constexpr insert_iterator(Container& x, ranges::iterator_t<Container> i);
    constexpr insert_iterator& operator=(const typename Container::value_type& value);
    constexpr insert_iterator& operator=(typename Container::value_type&& value);
 
    constexpr insert_iterator& operator*();
    constexpr insert_iterator& operator++();
    constexpr insert_iterator& operator++(int);
};

Class template std::move_iterator

template<class It>
class move_iterator {
public:
    using iterator_type     = It;
    using iterator_concept  = input_iterator_tag;
    using iterator_category = /* see definition */;
    using value_type        = iter_value_t<It>;
    using difference_type   = iter_difference_t<It>;
    using pointer           = It;
    using reference         = iter_rvalue_reference_t<It>;
 
    constexpr move_iterator();
    constexpr explicit move_iterator(It i);
    template<class U> constexpr move_iterator(const move_iterator<U>& u);
    template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);
 
    constexpr iterator_type base() const;
    constexpr reference operator*() const;
    constexpr pointer operator->() const;
 
    constexpr move_iterator& operator++();
    constexpr move_iterator operator++(int);
    constexpr move_iterator& operator--();
    constexpr move_iterator operator--(int);
 
    constexpr move_iterator operator+(difference_type n) const;
    constexpr move_iterator& operator+=(difference_type n);
    constexpr move_iterator operator-(difference_type n) const;
    constexpr move_iterator& operator-=(difference_type n);
    constexpr reference operator[](difference_type n) const;
 
    template<Sentinel<It> S>
        friend constexpr bool
            operator==(const move_iterator& x, const move_sentinel<S>& y);
    template<Sentinel<It> S>
        friend constexpr bool
            operator==(const move_sentinel<S>& x, const move_iterator& y);
    template<Sentinel<It> S>
        friend constexpr bool
            operator!=(const move_iterator& x, const move_sentinel<S>& y);
    template<Sentinel<It> S>
        friend constexpr bool
            operator!=(const move_sentinel<S>& x, const move_iterator& y);
    template<SizedSentinel<It> S>
        friend constexpr iter_difference_t<It>
            operator-(const move_sentinel<S>& x, const move_iterator& y);
    template<SizedSentinel<It> S>
        friend constexpr iter_difference_t<It>
            operator-(const move_iterator& x, const move_sentinel<S>& y);
    friend constexpr iter_rvalue_reference_t<It>
        iter_move(const move_iterator& i)
            noexcept(noexcept(ranges::iter_move(i.current)));
    template<IndirectlySwappable<It> It2>
        friend constexpr void
            iter_swap(const move_iterator& x, const move_iterator<It2>& y)
                noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
 
private:
    It current; // exposition only
};

Class template std::move_sentinel

template<Semiregular S>
class move_sentinel {
public:
    constexpr move_sentinel();
    constexpr explicit move_sentinel(S s);
    template<class S2>
        requires ConvertibleTo<const S2&, S>
            constexpr move_sentinel(const move_sentinel<S2>& s);
    template<class S2>
        requires Assignable<S&, const S2&>
            constexpr move_sentinel& operator=(const move_sentinel<S2>& s);
 
    constexpr S base() const;
private:
    S last;     // exposition only
};

Class template std::common_iterator

template<Iterator I, Sentinel<I> S>
    requires (!Same<I, S>)
class common_iterator {
public:
    constexpr common_iterator() = default;
    constexpr common_iterator(I i);
    constexpr common_iterator(S s);
    template<class I2, class S2>
        requires ConvertibleTo<const I2&, I> && ConvertibleTo<const S2&, S>
            constexpr common_iterator(const common_iterator<I2, S2>& x);
 
    template<class I2, class S2>
        requires ConvertibleTo<const I2&, I> && ConvertibleTo<const S2&, S> &&
                 Assignable<I&, const I2&> && Assignable<S&, const S2&>
            common_iterator& operator=(const common_iterator<I2, S2>& x);
 
    decltype(auto) operator*();
    decltype(auto) operator*() const
        requires __Dereferenceable<const I>;
    decltype(auto) operator->() const
        requires /* see definition */;
 
    common_iterator& operator++();
    decltype(auto) operator++(int);
 
    template<class I2, Sentinel<I> S2>
        requires Sentinel<S, I2>
    friend bool operator==(
        const common_iterator& x, const common_iterator<I2, S2>& y);
    template<class I2, Sentinel<I> S2>
      requires Sentinel<S, I2> && EqualityComparableWith<I, I2>
    friend bool operator==(
        const common_iterator& x, const common_iterator<I2, S2>& y);
    template<class I2, Sentinel<I> S2>
        requires Sentinel<S, I2>
    friend bool operator!=(
        const common_iterator& x, const common_iterator<I2, S2>& y);
 
    template<SizedSentinel<I> I2, SizedSentinel<I> S2>
        requires SizedSentinel<S, I2>
    friend iter_difference_t<I2> operator-(
        const common_iterator& x, const common_iterator<I2, S2>& y);
 
    friend iter_rvalue_reference_t<I> iter_move(const common_iterator& i)
        noexcept(noexcept(ranges::iter_move(declval<const I&>())))
            requires InputIterator<I>;
    template<IndirectlySwappable<I> I2, class S2>
        friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
            noexcept(noexcept(
                ranges::iter_swap(declval<const I&>(), declval<const I2&>())));
 
private:
    variant<I, S> v_;   // exposition only
};
 
template<class I, class S>
struct incrementable_traits<common_iterator<I, S>> {
    using difference_type = iter_difference_t<I>;
};
 
template<InputIterator I, class S>
struct iterator_traits<common_iterator<I, S>> {
    using iterator_concept = /* see definition */;
    using iterator_category = /* see definition */;
    using value_type = iter_value_t<I>;
    using difference_type = iter_difference_t<I>;
    using pointer = /* see definition */;
    using reference = iter_reference_t<I>;
};

Class std::default_sentinel_t

struct default_sentinel_t { };

Class template std::counted_iterator

template<Iterator I>
class counted_iterator {
public:
    using iterator_type = I;
 
    constexpr counted_iterator() = default;
    constexpr counted_iterator(I x, iter_difference_t<I> n);
    template<class I2>
        requires ConvertibleTo<const I2&, I>
            constexpr counted_iterator(const counted_iterator<I2>& x);
 
    template<class I2>
        requires Assignable<I&, const I2&>
            constexpr counted_iterator& operator=(const counted_iterator<I2>& x);
 
    constexpr I base() const;
    constexpr iter_difference_t<I> count() const noexcept;
    constexpr decltype(auto) operator*();
    constexpr decltype(auto) operator*() const
        requires __Dereferenceable<const I>;
 
    constexpr counted_iterator& operator++();
    decltype(auto) operator++(int);
    constexpr counted_iterator operator++(int)
        requires ForwardIterator<I>;
    constexpr counted_iterator& operator--()
        requires BidirectionalIterator<I>;
    constexpr counted_iterator operator--(int)
        requires BidirectionalIterator<I>;
 
    constexpr counted_iterator operator+(iter_difference_t<I> n) const
        requires RandomAccessIterator<I>;
    friend constexpr counted_iterator operator+(
        iter_difference_t<I> n, const counted_iterator& x)
            requires RandomAccessIterator<I>;
    constexpr counted_iterator& operator+=(iter_difference_t<I> n)
        requires RandomAccessIterator<I>;
 
    constexpr counted_iterator operator-(iter_difference_t<I> n) const
        requires RandomAccessIterator<I>;
    template<Common<I> I2>
        friend constexpr iter_difference_t<I2> operator-(
            const counted_iterator& x, const counted_iterator<I2>& y);
    friend constexpr iter_difference_t<I> operator-(
        const counted_iterator& x, default_sentinel_t);
    friend constexpr iter_difference_t<I> operator-(
        default_sentinel_t, const counted_iterator& y);
    constexpr counted_iterator& operator-=(iter_difference_t<I> n)
        requires RandomAccessIterator<I>;
 
    constexpr decltype(auto) operator[](iter_difference_t<I> n) const
        requires RandomAccessIterator<I>;
 
    template<Common<I> I2>
        friend constexpr bool operator==(
            const counted_iterator& x, const counted_iterator<I2>& y);
    friend constexpr bool operator==(
        const counted_iterator& x, default_sentinel_t);
    friend constexpr bool operator==(
        default_sentinel_t, const counted_iterator& x);
 
    template<Common<I> I2>
        friend constexpr bool operator!=(
            const counted_iterator& x, const counted_iterator<I2>& y);
    friend constexpr bool operator!=(
        const counted_iterator& x, default_sentinel_t y);
    friend constexpr bool operator!=(
        default_sentinel_t x, const counted_iterator& y);
 
    template<Common<I> I2>
        friend constexpr bool operator<(
            const counted_iterator& x, const counted_iterator<I2>& y);
    template<Common<I> I2>
        friend constexpr bool operator>(
            const counted_iterator& x, const counted_iterator<I2>& y);
    template<Common<I> I2>
        friend constexpr bool operator<=(
            const counted_iterator& x, const counted_iterator<I2>& y);
    template<Common<I> I2>
        friend constexpr bool operator>=(
            const counted_iterator& x, const counted_iterator<I2>& y);
 
    friend constexpr iter_rvalue_reference_t<I> iter_move(const counted_iterator& i)
        noexcept(noexcept(ranges::iter_move(i.current)))
            requires InputIterator<I>;
    template<IndirectlySwappable<I> I2>
        friend constexpr void iter_swap(const counted_iterator& x,
                                        const counted_iterator<I2>& y)
            noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
 
private:
    I current = I();                    // exposition only
    iter_difference_t<I> length = 0;    // exposition only
};
 
template<class I>
struct incrementable_traits<counted_iterator<I>> {
    using difference_type = iter_difference_t<I>;
};
 
template<InputIterator I>
struct iterator_traits<counted_iterator<I>> : iterator_traits<I> {
    using pointer = void;
};

Class std::unreachable_sentinel_t

struct unreachable_sentinel_t {
    template<WeaklyIncrementable I>
        friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept;
    template<WeaklyIncrementable I>
        friend constexpr bool operator==(const I&, unreachable_sentinel_t) noexcept;
    template<WeaklyIncrementable I>
        friend constexpr bool operator!=(unreachable_sentinel_t, const I&) noexcept;
    template<WeaklyIncrementable I>
        friend constexpr bool operator!=(const I&, unreachable_sentinel_t) noexcept;
};

Class template std::istream_iterator

template<class T, class CharT = char, class Traits = char_traits<CharT>,
         class Distance = ptrdiff_t>
class istream_iterator {
public:
    using iterator_category = input_iterator_tag;
    using value_type        = T;
    using difference_type   = Distance;
    using pointer           = const T*;
    using reference         = const T&;
    using char_type         = CharT;
    using traits_type       = Traits;
    using istream_type      = basic_istream<CharT, Traits>;
 
    constexpr istream_iterator();
    istream_iterator(istream_type& s);
    istream_iterator(const istream_iterator& x) = default;
    ~istream_iterator() = default;
 
    const T& operator*() const;
    const T* operator->() const;
    istream_iterator& operator++();
    istream_iterator operator++(int);
 
private:
    basic_istream<CharT, Traits>* in_stream; // exposition only
    T value;                                 // exposition only
};

Class template std::ostream_iterator

template<class T, class CharT = char, class Traits = char_traits<CharT>>
class ostream_iterator {
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using char_type         = CharT;
    using traits_type       = Traits;
    using ostream_type      = basic_ostream<CharT, Traits>;
 
    ostream_iterator(ostream_type& s);
    ostream_iterator(ostream_type& s, const CharT* delimiter);
    ostream_iterator(const ostream_iterator& x);
    ~ostream_iterator();
 
    ostream_iterator& operator=(const T& value);
    ostream_iterator& operator*();
    ostream_iterator& operator++();
    ostream_iterator& operator++(int);
 
private:
    basic_ostream<CharT, Traits>* out_stream; // exposition only
    const CharT* delim;                       // exposition only
};

Class template std::istreambuf_iterator

template<class CharT, class Traits = char_traits<CharT>>
class istreambuf_iterator {
public:
    using iterator_category = input_iterator_tag;
    using value_type        = CharT;
    using difference_type   = typename Traits::off_type;
    using pointer           = /*unspecified*/;
    using reference         = CharT;
    using char_type         = CharT;
    using traits_type       = Traits;
    using int_type          = typename Traits::int_type;
    using streambuf_type    = basic_streambuf<CharT, Traits>;
    using istream_type      = basic_istream<CharT, Traits>;
 
    class proxy; // exposition only
 
    constexpr istreambuf_iterator() noexcept;
    istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
    ~istreambuf_iterator() = default;
 
    istreambuf_iterator(istream_type& s) noexcept;
    istreambuf_iterator(streambuf_type* s) noexcept;
    istreambuf_iterator(const proxy& p) noexcept;
    CharT operator*() const;
    istreambuf_iterator& operator++();
    proxy operator++(int);
    bool equal(const istreambuf_iterator& b) const;
 
private:
    streambuf_type* sbuf_; // exposition only
};
 
template<class CharT, class Traits = char_traits<CharT>>
class istreambuf_iterator<CharT, Traits>::proxy { // exposition only
    CharT keep_;
    basic_streambuf<CharT, Traits>* sbuf_;
    proxy(CharT c, basic_streambuf<CharT, Traits>* sbuf)
        : keep_(c), sbuf_(sbuf) { }
public:
    CharT operator*() { return keep_; }
};

Class template std::ostreambuf_iterator

template<class CharT, class Traits = char_traits<CharT>>
class ostreambuf_iterator {
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using char_type         = CharT;
    using traits_type       = Traits;
    using streambuf_type    = basic_streambuf<CharT, Traits>;
    using ostream_type      = basic_ostream<CharT, Traits>;
 
    ostreambuf_iterator(ostream_type& s) noexcept;
    ostreambuf_iterator(streambuf_type* s) noexcept;
    ostreambuf_iterator& operator=(CharT c);
 
    ostreambuf_iterator& operator*();
    ostreambuf_iterator& operator++();
    ostreambuf_iterator& operator++(int);
    bool failed() const noexcept;
 
private:
    streambuf_type* sbuf_; // exposition only
};

Class template std::iterator

template<class Category, class T, class Distance = ptrdiff_t,
         class Pointer = T*, class Reference = T&>
struct iterator {
    typedef T           value_type;
    typedef Distance    difference_type;
    typedef Pointer     pointer;
    typedef Reference   reference;
    typedef Category    iterator_category;
};