23 Iterators library [iterators]

23.2 Header <iterator> synopsis [iterator.synopsis]

#include <concepts>

namespace std {
  template<class T> using with-reference = T&;  // exposition only
  template<class T> concept can-reference       // exposition only
    = requires { typename with-reference<T>; };
  template<class T> concept dereferenceable     // exposition only
    = requires(T& t) {
      { *t } -> can-reference;  // not required to be equality-preserving
    };

  // [iterator.assoc.types], associated types
  // [incrementable.traits], incrementable traits
  template<class> struct incrementable_traits;
  template<class T>
    using iter_difference_t = see below;

  // [readable.traits], readable traits
  template<class> struct readable_traits;
  template<class T>
    using iter_value_t = see below;

  // [iterator.traits], 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 {
    // [iterator.cust], customization points
    inline namespace unspecified {
      // [iterator.cust.move], ranges​::​iter_­move
      inline constexpr unspecified iter_move = unspecified;

      // [iterator.cust.swap], ranges​::​iter_­swap
      inline constexpr unspecified iter_swap = unspecified;
    }
  }

  template<dereferenceable T>
    requires requires(T& t) {
      { ranges::iter_move(t) } -> can-reference;
    }
  using iter_rvalue_reference_t
    = decltype(ranges::iter_move(declval<T&>()));

  // [iterator.concepts], iterator concepts
  // [iterator.concept.readable], concept Readable
  template<class In>
    concept Readable = see below;

  template<Readable T>
    using iter_common_reference_t =
      common_reference_t<iter_reference_t<T>, iter_value_t<T>&>;

  // [iterator.concept.writable], concept Writable
  template<class Out, class T>
    concept Writable = see below;

  // [iterator.concept.winc], concept WeaklyIncrementable
  template<class I>
    concept WeaklyIncrementable = see below;

  // [iterator.concept.inc], concept Incrementable
  template<class I>
    concept Incrementable = see below;

  // [iterator.concept.iterator], concept Iterator
  template<class I>
    concept Iterator = see below;

  // [iterator.concept.sentinel], concept Sentinel
  template<class S, class I>
    concept Sentinel = see below;

  // [iterator.concept.sizedsentinel], concept SizedSentinel
  template<class S, class I>
    inline constexpr bool disable_sized_sentinel = false;

  template<class S, class I>
    concept SizedSentinel = see below;

  // [iterator.concept.input], concept InputIterator
  template<class I>
    concept InputIterator = see below;

  // [iterator.concept.output], concept OutputIterator
  template<class I, class T>
    concept OutputIterator = see below;

  // [iterator.concept.forward], concept ForwardIterator
  template<class I>
    concept ForwardIterator = see below;

  // [iterator.concept.bidir], concept BidirectionalIterator
  template<class I>
    concept BidirectionalIterator = see below;

  // [iterator.concept.random.access], concept RandomAccessIterator
  template<class I>
    concept RandomAccessIterator = see below;

  // [iterator.concept.contiguous], concept ContiguousIterator
  template<class I>
    concept ContiguousIterator = see below;

  // [indirectcallable], indirect callable requirements
  // [indirectcallable.indirectinvocable], indirect callables
  template<class F, class I>
    concept IndirectUnaryInvocable = see below;

  template<class F, class I>
    concept IndirectRegularUnaryInvocable = see below;

  template<class F, class I>
    concept IndirectUnaryPredicate = see below;

  template<class F, class I1, class I2 = I1>
    concept IndirectRelation = see below;

  template<class F, class I1, class I2 = I1>
    concept IndirectStrictWeakOrder = see below;

  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], projected
  template<Readable I, IndirectRegularUnaryInvocable<I> Proj>
    struct projected;

  template<WeaklyIncrementable I, class Proj>
    struct incrementable_traits<projected<I, Proj>>;

  // [alg.req], common algorithm requirements
  // [alg.req.ind.move], concept IndirectlyMovable
  template<class In, class Out>
    concept IndirectlyMovable = see below;

  template<class In, class Out>
    concept IndirectlyMovableStorable = see below;

  // [alg.req.ind.copy], concept IndirectlyCopyable
  template<class In, class Out>
    concept IndirectlyCopyable = see below;

  template<class In, class Out>
    concept IndirectlyCopyableStorable = see below;

  // [alg.req.ind.swap], concept IndirectlySwappable
  template<class I1, class I2 = I1>
    concept IndirectlySwappable = see below;

  // [alg.req.ind.cmp], concept IndirectlyComparable
  template<class I1, class I2, class R, class P1 = identity, class P2 = identity>
    concept IndirectlyComparable = see below;

  // [alg.req.permutable], concept Permutable
  template<class I>
    concept Permutable = see below;

  // [alg.req.mergeable], concept Mergeable
  template<class I1, class I2, class Out,
      class R = ranges::less, class P1 = identity, class P2 = identity>
    concept Mergeable = see below;

  // [alg.req.sortable], concept Sortable
  template<class I, class R = ranges::less, class P = identity>
    concept Sortable = see below;

  // [iterator.primitives], primitives
  // [std.iterator.tags], 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], iterator operations
  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);
  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);

  // [range.iter.ops], range iterator operations
  namespace ranges {
    // [range.iter.op.advance], 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);

    // [range.iter.op.distance], 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);

    // [range.iter.op.next], 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);

    // [range.iter.op.prev], 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);
  }

  // [predef.iterators], predefined iterators and sentinels
  // [reverse.iterators], reverse iterators
  template<class Iterator> class reverse_iterator;

  template<class Iterator1, class Iterator2>
    constexpr bool operator==(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator!=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator<(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator>(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator<=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator>=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);

  template<class Iterator1, class Iterator2>
    constexpr auto operator-(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());
  template<class Iterator>
    constexpr reverse_iterator<Iterator>
      operator+(
    typename reverse_iterator<Iterator>::difference_type n,
    const reverse_iterator<Iterator>& x);

  template<class Iterator>
    constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);

  template<class Iterator1, class Iterator2>
      requires (!SizedSentinel<Iterator1, Iterator2>)
    inline constexpr bool disable_sized_sentinel<reverse_iterator<Iterator1>,
                                                 reverse_iterator<Iterator2>> = true;

  // [insert.iterators], 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], move iterators and sentinels
  template<class Iterator> class move_iterator;

  template<class Iterator1, class Iterator2>
    constexpr bool operator==(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator!=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator<(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator>(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator<=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template<class Iterator1, class Iterator2>
    constexpr bool operator>=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

  template<class Iterator1, class Iterator2>
    constexpr auto operator-(
    const move_iterator<Iterator1>& x,
    const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base());
  template<class Iterator>
    constexpr move_iterator<Iterator> operator+(
      typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& x);

  template<class Iterator>
    constexpr move_iterator<Iterator> make_move_iterator(Iterator i);

  template<Semiregular S> class move_sentinel;

  // [iterators.common], 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], default sentinels
  struct default_sentinel_t;
  inline constexpr default_sentinel_t default_sentinel{};

  // [iterators.counted], 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], unreachable sentinels
  struct unreachable_sentinel_t;
  inline constexpr unreachable_sentinel_t unreachable_sentinel{};

  // [stream.iterators], 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;

  // [iterator.range], 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 (&array)[N]) noexcept;
  template<class T, size_t N> constexpr T* end(T (&array)[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 (&array)[N]);
  template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[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 (&array)[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 (&array)[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 (&array)[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 (&array)[N]) noexcept;
  template<class E> constexpr const E* data(initializer_list<E> il) noexcept;
}