%!TEX root = std.tex
\rSec0[ranges]{Ranges library}

\rSec1[ranges.general]{General}

\pnum
This Clause describes components for dealing with ranges of elements.

\pnum
The following subclauses describe
range and view requirements, and
components for
range primitives and range generators
as summarized in \tref{range.summary}.

\begin{libsumtab}{Ranges library summary}{range.summary}
  \ref{range.access}       & Range access      & \tcode{<ranges>} \\
  \ref{range.req}          & Requirements      & \\
  \ref{range.utility}      & Range utilities   & \\
  \ref{range.factories}    & Range factories   & \\
  \ref{range.adaptors}     & Range adaptors    & \\ \rowsep
  \ref{coro.generator}     & Range generators  & \libheader{generator} \\
\end{libsumtab}

\rSec1[ranges.syn]{Header \tcode{<ranges>} synopsis}

\indexheader{ranges}%
\indexlibraryglobal{all_t}%
\begin{codeblock}
// mostly freestanding
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}
#include <iterator>             // see \ref{iterator.synopsis}

namespace std::ranges {
  inline namespace @\unspec@ {
    // \ref{range.access}, range access
    inline constexpr @\unspec@ begin = @\unspec@;
    inline constexpr @\unspec@ end = @\unspec@;
    inline constexpr @\unspec@ cbegin = @\unspec@;
    inline constexpr @\unspec@ cend = @\unspec@;
    inline constexpr @\unspec@ rbegin = @\unspec@;
    inline constexpr @\unspec@ rend = @\unspec@;
    inline constexpr @\unspec@ crbegin = @\unspec@;
    inline constexpr @\unspec@ crend = @\unspec@;

    inline constexpr @\unspec@ size = @\unspec@;
    inline constexpr @\unspec@ reserve_hint = @\unspec@;
    inline constexpr @\unspec@ ssize = @\unspec@;
    inline constexpr @\unspec@ empty = @\unspec@;
    inline constexpr @\unspec@ data = @\unspec@;
    inline constexpr @\unspec@ cdata = @\unspec@;
  }

  // \ref{range.range}, ranges
  template<class T>
    concept range = @\seebelow@;

  template<class T>
    constexpr bool enable_borrowed_range = false;

  template<class T>
    concept borrowed_range = @\seebelow@;

  template<class T>
    using @\libglobal{iterator_t}@ = decltype(ranges::begin(declval<T&>()));
  template<@\libconcept{range}@ R>
    using @\libglobal{sentinel_t}@ = decltype(ranges::end(declval<R&>()));
  template<@\libconcept{range}@ R>
    using @\libglobal{const_iterator_t}@ = decltype(ranges::cbegin(declval<R&>()));
  template<@\libconcept{range}@ R>
    using @\libglobal{const_sentinel_t}@ = decltype(ranges::cend(declval<R&>()));
  template<@\libconcept{range}@ R>
    using @\libglobal{range_difference_t}@ = iter_difference_t<iterator_t<R>>;
  template<@\libconcept{sized_range}@ R>
    using @\libglobal{range_size_t}@ = decltype(ranges::size(declval<R&>()));
  template<@\libconcept{range}@ R>
    using @\libglobal{range_value_t}@ = iter_value_t<iterator_t<R>>;
  template<@\libconcept{range}@ R>
    using @\libglobal{range_reference_t}@ = iter_reference_t<iterator_t<R>>;
  template<@\libconcept{range}@ R>
    using @\libglobal{range_const_reference_t}@ = iter_const_reference_t<iterator_t<R>>;
  template<@\libconcept{range}@ R>
    using @\libglobal{range_rvalue_reference_t}@ = iter_rvalue_reference_t<iterator_t<R>>;
  template<@\libconcept{range}@ R>
    using @\libglobal{range_common_reference_t}@ = iter_common_reference_t<iterator_t<R>>;

  // \ref{range.sized}, sized ranges
  template<class>
    constexpr bool disable_sized_range = false;

  template<class T>
    concept approximately_sized_range = @\seebelow@;

  template<class T>
    concept sized_range = @\seebelow@;

  // \ref{range.view}, views
  template<class T>
    constexpr bool enable_view = @\seebelow@;

  struct view_base {};

  template<class T>
    concept view = @\seebelow@;

  // \ref{range.refinements}, other range refinements
  template<class R, class T>
    concept output_range = @\seebelow@;

  template<class T>
    concept input_range = @\seebelow@;

  template<class T>
    concept forward_range = @\seebelow@;

  template<class T>
    concept bidirectional_range = @\seebelow@;

  template<class T>
    concept random_access_range = @\seebelow@;

  template<class T>
    concept contiguous_range = @\seebelow@;

  template<class T>
    concept common_range = @\seebelow@;

  template<class T>
    concept viewable_range = @\seebelow@;

  template<class T>
    concept constant_range = @\seebelow@;

  template<class T>
    concept @\defexposconcept{sized-random-access-range}@ = @\seebelownc@;              // \expos

  // \ref{view.interface}, class template \tcode{view_interface}
  template<class D>
    requires is_class_v<D> && @\libconcept{same_as}@<D, remove_cv_t<D>>
  class view_interface;

  // \ref{range.subrange}, sub-ranges
  enum class @\libglobal{subrange_kind}@ : bool { @\libmember{unsized}{subrange_kind}@, @\libmember{sized}{subrange_kind}@ };

  template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@<I> S = I, subrange_kind K = @\seebelow@>
    requires (K == subrange_kind::sized || !@\libconcept{sized_sentinel_for}@<S, I>)
  class subrange;

  template<class I, class S, subrange_kind K>
    constexpr bool @\libspec{enable_borrowed_range}{subrange}@<subrange<I, S, K>> = true;

  template<size_t N, class I, class S, subrange_kind K>
    requires ((N == 0 && @\libconcept{copyable}@<I>) || N == 1)
    constexpr auto get(const subrange<I, S, K>& r);

  template<size_t N, class I, class S, subrange_kind K>
    requires (N < 2)
    constexpr auto get(subrange<I, S, K>&& r);
}

namespace std {
  using ranges::get;
}

namespace std::ranges {
  // \ref{range.dangling}, dangling iterator handling
  struct dangling;

  // \ref{range.elementsof}, class template \tcode{elements_of}
  template<@\libconcept{range}@ R, class Allocator = allocator<byte>>
    struct elements_of;                                                             // hosted

  template<@\libconcept{range}@ R>
    using borrowed_iterator_t = @\seebelow@;

  template<@\libconcept{range}@ R>
    using borrowed_subrange_t = @\seebelow@;

  // \ref{range.utility.conv}, range conversions
  template<class C, @\libconcept{input_range}@ R, class... Args> requires (!@\libconcept{view}@<C>)
    constexpr C to(R&& r, Args&&... args);
  template<template<class...> class C, @\libconcept{input_range}@ R, class... Args>
    constexpr auto to(R&& r, Args&&... args);
  template<class C, class... Args> requires (!@\libconcept{view}@<C>)
    constexpr auto to(Args&&... args);
  template<template<class...> class C, class... Args>
    constexpr auto to(Args&&... args);

  // \ref{range.empty}, empty view
  template<class T>
    requires is_object_v<T>
  class empty_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{empty_view}@<empty_view<T>> = true;

  namespace views {
    template<class T>
      constexpr empty_view<T> @\libmember{empty}{views}@{};
  }

  // \ref{range.single}, single view
  template<@\libconcept{move_constructible}@ T>
    requires is_object_v<T>
  class single_view;

  namespace views { inline constexpr @\unspecnc@ single = @\unspecnc@; }

  template<bool Const, class T>
    using @\exposidnc{maybe-const}@ = conditional_t<Const, const T, T>;   // \expos

  // \ref{range.iota}, iota view
  template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t>
    requires @\exposconcept{weakly-equality-comparable-with}@<W, Bound> && @\libconcept{copyable}@<W>
  class iota_view;

  template<class W, class Bound>
    constexpr bool @\libspec{enable_borrowed_range}{iota_view}@<iota_view<W, Bound>> = true;

  namespace views {
    inline constexpr @\unspecnc@ iota = @\unspecnc@;
    inline constexpr @\unspecnc@ indices = @\unspecnc@;
  }

  // \ref{range.repeat}, repeat view
  template<@\libconcept{move_constructible}@ T, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t>
    requires @\seebelow@
  class repeat_view;

  namespace views { inline constexpr @\unspecnc@ repeat = @\unspecnc@; }

  // \ref{range.istream}, istream view
  template<@\libconcept{movable}@ Val, class CharT, class Traits = char_traits<CharT>>
    requires @\seebelow@
  class basic_istream_view;                                                         // hosted
  template<class Val>
    using @\libglobal{istream_view}@ = basic_istream_view<Val, char>;                             // hosted
  template<class Val>
    using @\libglobal{wistream_view}@ = basic_istream_view<Val, wchar_t>;                         // hosted

  namespace views {
    template<class T> constexpr @\unspecnc@ istream = @\unspecnc@;                  // hosted
  }

  // \ref{range.adaptor.object}, range adaptor objects
  template<class D>
    requires is_class_v<D> && @\libconcept{same_as}@<D, remove_cv_t<D>>
  class range_adaptor_closure { };

  // \ref{range.all}, all view
  namespace views {
    inline constexpr @\unspecnc@ all = @\unspecnc@;

    template<@\libconcept{viewable_range}@ R>
      using all_t = decltype(all(declval<R>()));
  }

  // \ref{range.ref.view}, ref view
  template<@\libconcept{range}@ R>
    requires is_object_v<R>
  class ref_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{ref_view}@<ref_view<T>> = true;

  // \ref{range.owning.view}, owning view
  template<@\libconcept{range}@ R>
    requires @\seebelow@
  class owning_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{owning_view}@<owning_view<T>> =
      enable_borrowed_range<T>;

  // \ref{range.as.rvalue}, as rvalue view
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class as_rvalue_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{as_rvalue_view}@<as_rvalue_view<T>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ as_rvalue = @\unspecnc@; }

  // \ref{range.filter}, filter view
  template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@<iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  class filter_view;

  namespace views { inline constexpr @\unspecnc@ filter = @\unspecnc@; }

  // \ref{range.transform}, transform view
  template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F>
    requires @\libconcept{view}@<V> && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, range_reference_t<V>> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<V>>>
  class transform_view;

  namespace views { inline constexpr @\unspecnc@ transform = @\unspecnc@; }

  // \ref{range.take}, take view
  template<@\libconcept{view}@> class take_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{take_view}@<take_view<T>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ take = @\unspecnc@; }

  // \ref{range.take.while}, take while view
  template<@\libconcept{view}@ V, class Pred>
    requires @\libconcept{input_range}@<V> && is_object_v<Pred> &&
             @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<V>>
    class take_while_view;

  namespace views { inline constexpr @\unspecnc@ take_while = @\unspecnc@; }

  // \ref{range.drop}, drop view
  template<@\libconcept{view}@ V>
    class drop_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{drop_view}@<drop_view<T>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ drop = @\unspecnc@; }

  // \ref{range.drop.while}, drop while view
  template<@\libconcept{view}@ V, class Pred>
    requires @\libconcept{input_range}@<V> && is_object_v<Pred> &&
             @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<V>>
    class drop_while_view;

  template<class T, class Pred>
    constexpr bool @\libspec{enable_borrowed_range}{drop_while_view}@<drop_while_view<T, Pred>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ drop_while = @\unspecnc@; }

  // \ref{range.join}, join view
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
  class join_view;

  namespace views { inline constexpr @\unspecnc@ join = @\unspecnc@; }

  // \ref{range.join.with}, join with view
  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\seebelow@
  class join_with_view;

  namespace views { inline constexpr @\unspecnc@ join_with = @\unspecnc@; }

  // \ref{range.lazy.split}, lazy split view
  template<class R>
    concept @\exposconcept{tiny-range}@ = @\seebelow@;   // \expos

  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (@\libconcept{forward_range}@<V> || @\exposconcept{tiny-range}@<Pattern>)
  class lazy_split_view;

  // \ref{range.split}, split view
  template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  class split_view;

  namespace views {
    inline constexpr @\unspecnc@ lazy_split = @\unspecnc@;
    inline constexpr @\unspecnc@ split = @\unspecnc@;
  }

  // \ref{range.concat}, concat view
  template<@\libconcept{input_range}@... Views>
    requires @\seebelow@
  class concat_view;

  namespace views { inline constexpr @\unspecnc@ concat = @\unspecnc@; }

  // \ref{range.counted}, counted view
  namespace views { inline constexpr @\unspecnc@ counted = @\unspecnc@; }

  // \ref{range.common}, common view
  template<@\libconcept{view}@ V>
    requires (!@\libconcept{common_range}@<V> && @\libconcept{copyable}@<iterator_t<V>>)
  class common_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{common_view}@<common_view<T>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ common = @\unspecnc@; }

  // \ref{range.reverse}, reverse view
  template<@\libconcept{view}@ V>
    requires @\libconcept{bidirectional_range}@<V>
  class reverse_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{reverse_view}@<reverse_view<T>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ reverse = @\unspecnc@; }

  // \ref{range.as.const}, as const view
  template<@\libconcept{input_range}@ R>
    constexpr auto& @\exposid{possibly-const-range}@(R& r) noexcept { // \expos
      if constexpr (@\libconcept{input_range}@<const R>) {
        return const_cast<const R&>(r);
      } else {
        return r;
      }
    }

  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class as_const_view;

  template<class T>
    constexpr bool @\libspec{enable_borrowed_range}{as_const_view}@<as_const_view<T>> =
      enable_borrowed_range<T>;

  namespace views { inline constexpr @\unspecnc@ as_const = @\unspecnc@; }

  // \ref{range.elements}, elements view
  template<@\libconcept{input_range}@ V, size_t N>
    requires @\seebelow@
  class elements_view;

  template<class T, size_t N>
    constexpr bool @\libspec{enable_borrowed_range}{elements_view}@<elements_view<T, N>> =
      enable_borrowed_range<T>;

  template<class R>
    using @\libglobal{keys_view}@ = elements_view<R, 0>;
  template<class R>
    using @\libglobal{values_view}@ = elements_view<R, 1>;

  namespace views {
    template<size_t N>
      constexpr @\unspecnc@ elements = @\unspecnc@;
    inline constexpr auto @\libmember{keys}{views}@ = elements<0>;
    inline constexpr auto @\libmember{values}{views}@ = elements<1>;
  }

  // \ref{range.enumerate}, enumerate view
  template<@\libconcept{view}@ V>
    requires @\seebelow@
  class enumerate_view;

  template<class View>
    constexpr bool @\libspec{enable_borrowed_range}{enumerate_view}@<enumerate_view<View>> =
      enable_borrowed_range<View>;

  namespace views { inline constexpr @\unspecnc@ enumerate = @\unspecnc@; }

  // \ref{range.zip}, zip view
  template<@\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0)
  class zip_view;

  template<class... Views>
    constexpr bool @\libspec{enable_borrowed_range}{zip_view}@<zip_view<Views...>> =
      (enable_borrowed_range<Views> && ...);

  namespace views { inline constexpr @\unspecnc@ zip = @\unspecnc@; }

  // \ref{range.zip.transform}, zip transform view
  template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, range_reference_t<Views>...> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<Views>...>>
  class zip_transform_view;

  namespace views { inline constexpr @\unspecnc@ zip_transform = @\unspecnc@; }

  // \ref{range.adjacent}, adjacent view
  template<@\libconcept{forward_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && (N > 0)
  class adjacent_view;

  template<class V, size_t N>
    constexpr bool @\libspec{enable_borrowed_range}{adjacent_view}@<adjacent_view<V, N>> =
      enable_borrowed_range<V>;

  namespace views {
    template<size_t N>
      constexpr @\unspecnc@ adjacent = @\unspecnc@;
    inline constexpr auto @\libmember{pairwise}{views}@ = adjacent<2>;
  }

  // \ref{range.adjacent.transform}, adjacent transform view
  template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N>
    requires @\seebelow@
  class adjacent_transform_view;

  namespace views {
    template<size_t N>
      constexpr @\unspecnc@ adjacent_transform = @\unspecnc@;
    inline constexpr auto @\libmember{pairwise_transform}{views}@ = adjacent_transform<2>;
  }

  // \ref{range.chunk}, chunk view
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class chunk_view;

  template<@\libconcept{view}@ V>
    requires @\libconcept{forward_range}@<V>
  class chunk_view<V>;

  template<class V>
    constexpr bool @\libspec{enable_borrowed_range}{chunk_view}@<chunk_view<V>> =
      @\libconcept{forward_range}@<V> && enable_borrowed_range<V>;

  namespace views { inline constexpr @\unspecnc@ chunk = @\unspecnc@; }

  // \ref{range.slide}, slide view
  template<@\libconcept{forward_range}@ V>
    requires @\libconcept{view}@<V>
  class slide_view;

  template<class V>
    constexpr bool @\libspec{enable_borrowed_range}{slide_view}@<slide_view<V>> =
      enable_borrowed_range<V>;

  namespace views { inline constexpr @\unspecnc@ slide = @\unspecnc@; }

  // \ref{range.chunk.by}, chunk by view
  template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@<iterator_t<V>, iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  class chunk_by_view;

  namespace views { inline constexpr @\unspecnc@ chunk_by = @\unspecnc@; }

  // \ref{range.stride}, stride view
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class stride_view;

  template<class V>
    constexpr bool @\libspec{enable_borrowed_range}{stride_view}@<stride_view<V>> =
      enable_borrowed_range<V>;

  namespace views { inline constexpr @\unspecnc@ stride = @\unspecnc@; }

  // \ref{range.cartesian}, cartesian product view
  template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs>
    requires (@\libconcept{view}@<First> && ... && @\libconcept{view}@<Vs>)
  class cartesian_product_view;

  namespace views { inline constexpr @\unspecnc@ cartesian_product = @\unspecnc@; }

  // \ref{range.cache.latest}, cache latest view
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class cache_latest_view;

  namespace views { inline constexpr @\unspec@ cache_latest = @\unspec@; }

  // \ref{range.as.input}, as input view
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class as_input_view;

  template<class V>
    constexpr bool enable_borrowed_range<as_input_view<V>> =
      enable_borrowed_range<V>;

  namespace views { inline constexpr @\unspec@ as_input = @\unspec@; }
}

namespace std {
  namespace views = ranges::views;

  template<class T> struct tuple_size;
  template<size_t I, class T> struct tuple_element;

  template<class I, class S, ranges::subrange_kind K>
  struct tuple_size<ranges::subrange<I, S, K>>
    : integral_constant<size_t, 2> {};
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<0, ranges::subrange<I, S, K>> {
    using type = I;
  };
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<1, ranges::subrange<I, S, K>> {
    using type = S;
  };
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<0, const ranges::subrange<I, S, K>> {
    using type = I;
  };
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<1, const ranges::subrange<I, S, K>> {
    using type = S;
  };

  struct from_range_t { explicit from_range_t() = default; };
  inline constexpr from_range_t from_range{};
}
\end{codeblock}

\pnum
\indextext{to-unsigned-like@\exposid{to-unsigned-like}}%
\indextext{make-unsigned-like-t@\exposid{make-unsigned-like-t}}%
Within this Clause,
for an integer-like type \tcode{X}\iref{iterator.concept.winc},
\tcode{\placeholdernc{make-unsigned-like-t}<X>} denotes
\tcode{make_unsigned_t<X>} if \tcode{X} is an integer type;
otherwise, it denotes a corresponding unspecified unsigned-integer-like type
of the same width as \tcode{X}.
For an expression \tcode{x} of type \tcode{X},
\tcode{\placeholdernc{to-unsigned-like}(x)} is
\tcode{x} explicitly converted to
\tcode{\placeholdernc{make-unsigned-like-t}<X>}.

\pnum
Also within this Clause,
\tcode{\exposid{make-signed-like-t}<X>} for an integer-like type \tcode{X}
denotes \tcode{make_signed_t<X>} if \tcode{X} is an integer type;
otherwise, it denotes a corresponding unspecified signed-integer-like type
of the same width as \tcode{X}.

\rSec1[range.access]{Range access}

\rSec2[range.access.general]{General}

\pnum
In addition to being available via inclusion of the \libheader{ranges}
header, the customization point objects in \ref{range.access} are
available when the header \libheaderrefx{iterator}{iterator.synopsis} is included.

\pnum
Within \ref{range.access},
the \defnadj{reified}{object} of a subexpression \tcode{E} denotes
\begin{itemize}
\item
the same object as \tcode{E} if \tcode{E} is a glvalue, or
\item
the result of applying
the temporary materialization conversion\iref{conv.rval} to \tcode{E} otherwise.
\end{itemize}

\rSec2[range.access.begin]{\tcode{ranges::begin}}
\indexlibraryglobal{begin}%

\pnum
The name \tcode{ranges::begin} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{E} is an rvalue and
  \tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
  \tcode{ranges::begin(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array type\iref{term.array.type} and
  \tcode{remove_all_extents_t<T>} is an incomplete type,
  \tcode{ranges::begin(E)} is ill-formed with no diagnostic required.

\item
  Otherwise, if \tcode{T} is an array type,
  \tcode{ranges::begin(E)} is expression-equivalent to \tcode{t + 0}.

\item
  Otherwise, if \tcode{auto(t.begin())}
  is a valid expression whose type models
  \libconcept{input_or_output_iterator},
  \tcode{ranges::begin(E)} is expression-equivalent to
  \tcode{auto(t.begin())}.

\item
  Otherwise, if \tcode{T} is a class or enumeration type and
  \tcode{auto(begin(t))}
  is a valid expression whose type models
  \libconcept{input_or_output_iterator}
  where the meaning of \tcode{begin} is established as-if by performing
  argument-dependent lookup only\iref{basic.lookup.argdep},
  then \tcode{ranges::begin(E)} is expression-equivalent to
  that expression.

\item
  Otherwise, \tcode{ranges::begin(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above
result in substitution failure when \tcode{ranges::begin(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::begin(E)} is a valid expression, its type models
\libconcept{input_or_output_iterator}.
\end{note}

\rSec2[range.access.end]{\tcode{ranges::end}}
\indexlibraryglobal{end}%

\pnum
The name \tcode{ranges::end} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{E} is an rvalue and
  \tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
  \tcode{ranges::end(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array type\iref{term.array.type} and
  \tcode{remove_all_extents_t<T>} is an incomplete type,
  \tcode{ranges::end(E)} is ill-formed with no diagnostic required.

\item
  Otherwise, if \tcode{T} is an array of unknown bound,
  \tcode{ranges::end(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array,
  \tcode{ranges::end(E)} is expression-equivalent to
  \tcode{t + extent_v<T>}.

\item
  Otherwise, if \tcode{auto(t.end())}
  is a valid expression whose type models
  \tcode{\libconcept{sentinel_for}<iterator_t<T>>}
  then \tcode{ranges::end(E)} is expression-equivalent to
  \tcode{auto(t.end())}.

\item
  Otherwise, if \tcode{T} is a class or enumeration type and
  \tcode{auto(end(t))}
  is a valid expression whose type models
  \tcode{\libconcept{sentinel_for}<iterator_t<T>>}
  where the meaning of \tcode{end} is established as-if by performing
  argument-dependent lookup only\iref{basic.lookup.argdep},
  then \tcode{ranges::end(E)} is expression-equivalent to
  that expression.

\item
  Otherwise, \tcode{ranges::end(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above
result in substitution failure when \tcode{ranges::end(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::end(E)} is a valid expression,
the types \tcode{S} and \tcode{I} of
\tcode{ranges::end(E)} and \tcode{ranges::begin(E)}
model \tcode{\libconcept{sentinel_for}<S, I>}.
\end{note}

\rSec2[range.access.cbegin]{\tcode{ranges::cbegin}}
\indexlibraryglobal{cbegin}%

\pnum
The name \tcode{ranges::cbegin} denotes a customization point
object\iref{customization.point.object}.
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:
\begin{itemize}
\item
If \tcode{E} is an rvalue and
\tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
\tcode{ranges::cbegin(E)} is ill-formed.
\item
Otherwise,
let \tcode{U} be \tcode{ranges::begin(\exposid{possibly-const-range}(t))}.
\tcode{ranges::cbegin(E)} is expression-equivalent to
\tcode{const_iterator<decltype(U)>(U)}.
\end{itemize}

\pnum
\begin{note}
Whenever \tcode{ranges::cbegin(E)} is a valid expression, its type models
\libconcept{input_or_output_iterator} and \exposconcept{constant-iterator}.
\end{note}

\rSec2[range.access.cend]{\tcode{ranges::cend}}
\indexlibraryglobal{cend}%

\pnum
The name \tcode{ranges::cend} denotes a customization point
object\iref{customization.point.object}.
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:
\begin{itemize}
\item
If \tcode{E} is an rvalue and
\tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
\tcode{ranges::cend(E)} is ill-formed.
\item
Otherwise,
let \tcode{U} be \tcode{ranges::end(\exposid{possibly-const-range}(t))}.
\tcode{ranges::cend(E)} is expression-equivalent to
\tcode{const_sentinel<decltype(U)>(U)}.
\end{itemize}

\pnum
\begin{note}
Whenever \tcode{ranges::cend(E)} is a valid expression,
the types \tcode{S} and \tcode{I} of the expressions
\tcode{ranges::cend(E)} and \tcode{ranges::cbegin(E)}
model \tcode{\libconcept{sentinel_for}<S, I>}.
If \tcode{S} models \libconcept{input_iterator},
then \tcode{S} also models \exposconceptx{constant-itera\-tor}{constant-iterator}.
\end{note}

\rSec2[range.access.rbegin]{\tcode{ranges::rbegin}}
\indexlibraryglobal{rbegin}%

\pnum
The name \tcode{ranges::rbegin} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{E} is an rvalue and
  \tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
  \tcode{ranges::rbegin(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array type\iref{term.array.type} and
  \tcode{remove_all_extents_t<T>} is an incomplete type,
  \tcode{ranges::rbegin(E)} is ill-formed with no diagnostic required.

\item
  Otherwise, if \tcode{auto(t.rbegin())}
  is a valid expression whose type models
  \libconcept{input_or_output_iterator},
  \tcode{ranges::rbegin(E)} is expression-equivalent to
  \tcode{auto(t.rbegin())}.

\item
  Otherwise, if \tcode{T} is a class or enumeration type and
  \tcode{auto(rbegin(t))}
  is a valid expression whose type models
  \libconcept{input_or_output_iterator}
  where the meaning of \tcode{rbegin} is established as-if by performing
  argument-dependent lookup only\iref{basic.lookup.argdep},
  then \tcode{ranges::rbegin(E)} is expression-equivalent to
  that expression.

\item
  Otherwise, if both \tcode{ranges::begin(t)} and \tcode{ranges::end(t)}
  are valid expressions of the same type which models
  \libconcept{bidirectional_iterator}\iref{iterator.concept.bidir},
  \tcode{ranges::rbegin(E)} is expression-equivalent to
  \tcode{make_reverse_iterator(ranges::end(t))}.

\item
  Otherwise, \tcode{ranges::rbegin(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above result in substitution failure
when \tcode{ranges::rbegin(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::rbegin(E)} is a valid expression, its type models
\libconcept{input_or_output_iterator}.
\end{note}

\rSec2[range.access.rend]{\tcode{ranges::rend}}
\indexlibraryglobal{rend}%

\pnum
The name \tcode{ranges::rend} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{E} is an rvalue and
  \tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
  \tcode{ranges::rend(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array type\iref{term.array.type} and
  \tcode{remove_all_extents_t<T>} is an incomplete type,
  \tcode{ranges::rend(E)} is ill-formed with no diagnostic required.

\item
  Otherwise, if \tcode{auto(t.rend())}
  is a valid expression whose type models
  \tcode{\libconcept{sentinel_for}<decltype(\brk{}ranges::rbegin(E))>}
  then \tcode{ranges::rend(E)} is expression-equivalent to
  \tcode{auto(t.rend())}.

\item
  Otherwise, if \tcode{T} is a class or enumeration type and
  \tcode{auto(rend(t))}
  is a valid expression whose type models
  \tcode{\libconcept{sentinel_for}<decltype(ranges::rbegin(E))>}
  where the meaning of \tcode{rend} is established as-if by performing
  argument-dependent lookup only\iref{basic.lookup.argdep},
  then \tcode{ranges::rend(E)} is expression-equivalent to
  that expression.

\item
  Otherwise, if both \tcode{ranges::begin(t)} and \tcode{ranges::end(t)}
  are valid expressions of the same type which models
  \libconcept{bidirectional_iterator}\iref{iterator.concept.bidir},
  then \tcode{ranges::rend(E)} is expression-equivalent to
  \tcode{make_reverse_iterator(ranges::begin(t))}.

\item
  Otherwise, \tcode{ranges::rend(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above
result in substitution failure when \tcode{ranges::rend(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::rend(E)} is a valid expression,
the types \tcode{S} and \tcode{I} of the expressions
\tcode{ranges::rend(E)} and \tcode{ranges::rbegin(E)}
model \tcode{\libconcept{sentinel_for}<S, I>}.
\end{note}

\rSec2[range.access.crbegin]{\tcode{ranges::crbegin}}
\indexlibraryglobal{crbegin}%

\pnum
The name \tcode{ranges::crbegin} denotes a customization point
object\iref{customization.point.object}.
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:
\begin{itemize}
\item
If \tcode{E} is an rvalue and
\tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
\tcode{ranges::crbegin(E)} is ill-formed.
\item
Otherwise,
let \tcode{U} be \tcode{ranges::rbegin(\exposid{possibly-const-range}(t))}.
\tcode{ranges::crbegin(E)} is expres\-sion-equivalent to
\tcode{const_iterator<decltype(U)>(U)}.
\end{itemize}

\pnum
\begin{note}
Whenever \tcode{ranges::crbegin(E)} is a valid expression, its
type models \libconcept{input_or_output_iterator} and
\exposconcept{constant-iterator}.
\end{note}

\rSec2[range.access.crend]{\tcode{ranges::crend}}
\indexlibraryglobal{crend}%

\pnum
The name \tcode{ranges::crend} denotes a customization point
object\iref{customization.point.object}.
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:
\begin{itemize}
\item
If \tcode{E} is an rvalue and
\tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
\tcode{ranges::crend(E)} is ill-formed.
\item
Otherwise,
let \tcode{U} be \tcode{ranges::rend(\exposid{possibly-const-range}(t))}.
\tcode{ranges::crend(E)} is expression-equivalent to
\tcode{const_sentinel<decltype(U)>(U)}.
\end{itemize}

\pnum
\begin{note}
Whenever \tcode{ranges::crend(E)} is a valid expression,
the types \tcode{S} and \tcode{I} of the expressions
\tcode{ranges::crend(E)} and \tcode{ranges::crbegin(E)}
model \tcode{\libconcept{sentinel_for}<S, I>}.
If \tcode{S} models \libconcept{input_iterator},
then \tcode{S} also models \exposconceptx{constant-itera\-tor}{constant-iterator}.
\end{note}

\rSec2[range.prim.size]{\tcode{ranges::size}}
\indexlibraryglobal{size}%

\pnum
The name \tcode{ranges::size} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{T} is an array of unknown bound\iref{term.array.type},
  \tcode{ranges::size(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array type,
  \tcode{ranges::size(E)} is expression-equivalent to
  \tcode{auto(extent_v<T>)}.

\item
  Otherwise, if \tcode{disable_sized_range<remove_cv_t<T>>}\iref{range.sized}
  is \tcode{false} and
  \tcode{auto(t.size())}
  is a valid expression of integer-like type\iref{iterator.concept.winc},
  \tcode{ranges::size(E)} is expression-equivalent to
  \tcode{auto(\brk{}t.size())}.

\item
  Otherwise, if \tcode{T} is a class or enumeration type,
  \tcode{disable_sized_range<remove_cv_t<T>>} is \tcode{false} and
  \tcode{auto(size(t))}
  is a valid expression of integer-like type
  where the meaning of \tcode{size} is established as-if by performing
  argument-dependent lookup only\iref{basic.lookup.argdep},
  then \tcode{ranges::size(E)} is expression-equivalent to
  that expression.

\item
  Otherwise, if
  \tcode{\placeholdernc{to-unsigned-like}(ranges::end(t) - ranges::begin(t))}\iref{ranges.syn}
  is a valid expression and
  the types \tcode{I} and \tcode{S} of \tcode{ranges::begin(t)} and
  \tcode{ranges::end(t)} (respectively) model both
  \tcode{\libconcept{sized_sentinel_for}<S, I>}\iref{iterator.concept.sizedsentinel} and
  \tcode{\libconcept{forward_iterator}<I>},
  then \tcode{ranges::size(E)} is expres\-sion-equivalent to
  \tcode{\placeholdernc{to-unsigned-like}(ranges::end(t) - ranges::begin(t))}.

\item
  Otherwise, \tcode{ranges::size(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above
result in substitution failure when \tcode{ranges::size(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::size(E)} is a valid expression, its
type is integer-like.
\end{note}

\rSec2[range.prim.ssize]{\tcode{ranges::ssize}}
\indexlibraryglobal{ssize}%

\pnum
The name \tcode{ranges::ssize} denotes
a customization point object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
If \tcode{ranges::size(t)} is ill-formed,
\tcode{ranges::ssize(E)} is ill-formed.
Otherwise let \tcode{D} be
\tcode{\exposid{make-signed-like-t}<decltype(ranges::\brk{}size(t))>}, or
\tcode{ptrdiff_t} if it is wider than that type;
\tcode{ranges::ssize(E)} is expression-equivalent to
\tcode{static_cast<D>(ranges::size(t))}.

\rSec2[range.prim.size.hint]{\tcode{ranges::reserve_hint}}
\indexlibraryglobal{reserve_hint}%

\pnum
The name \tcode{ranges::reserve_hint} denotes
a customization point object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:
\begin{itemize}
\item
If \tcode{ranges::size(E)} is a valid expression,
\tcode{ranges::reserve_hint(E)} is expression-equivalent to
\tcode{ranges::size(E)}.
\item
Otherwise,
if \tcode{auto(t.reserve_hint())} is a valid expression of
integer-like type\iref{iterator.concept.winc},
\tcode{ranges::re\-serve_hint(E)} is expression-equivalent to
\tcode{auto(t.reserve_hint())}.
\item
Otherwise,
if \tcode{T} is a class or enumeration type and
\tcode{auto(reserve_hint(t))} is a valid expression of
integer-like type where
the meaning of \tcode{reserve_hint} is established as-if by
performing argument-dependent lookup only\iref{basic.lookup.argdep}, then
\tcode{ranges::reserve_hint(E)} is expression-equivalent to that expression.
\item
Otherwise,
\tcode{ranges::reserve_hint(E)} is ill-formed.
\end{itemize}
\begin{note}
Diagnosable ill-formed cases above result in substitution failure when
\tcode{ranges::reserve_hint(E)} appears in the immediate context of
a template instantiation.
\end{note}
\begin{note}
Whenever \tcode{ranges::reserve_hint(E)} is a valid expression,
its type is integer-like.
\end{note}

\rSec2[range.prim.empty]{\tcode{ranges::empty}}
\indexlibraryglobal{empty}%

\pnum
The name \tcode{ranges::empty} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{T} is an array of unknown bound\iref{term.array.type},
  \tcode{ranges::empty(E)} is ill-formed.

\item
  Otherwise, if \tcode{bool(t.empty())} is a valid expression,
  \tcode{ranges::empty(E)} is expression-equivalent to
  \tcode{bool(t.empty())}.

\item
  Otherwise, if \tcode{(ranges::size(t) == 0)} is a valid expression,
  \tcode{ranges::empty(E)} is expression-equiva\-lent to
  \tcode{(ranges::size(t) == 0)}.

\item
  Otherwise, if \tcode{bool(ranges::begin(t) == ranges::end(t))}
  is a valid expression and
  the type of \tcode{ranges::begin(t)} models \libconcept{forward_iterator},
  \tcode{ranges::empty(E)} is expression-equivalent to
  \tcode{bool(\brk{}ranges::begin(t) == ranges::end(t))}.

\item
  Otherwise, \tcode{ranges::empty(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above
result in substitution failure when \tcode{ranges::empty(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::empty(E)} is a valid expression,
it has type \tcode{bool}.
\end{note}

\rSec2[range.prim.data]{\tcode{ranges::data}}
\indexlibraryglobal{data}%

\pnum
The name \tcode{ranges::data} denotes a customization point
object\iref{customization.point.object}.

\pnum
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:

\begin{itemize}
\item
  If \tcode{E} is an rvalue and
  \tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
  \tcode{ranges::data(E)} is ill-formed.

\item
  Otherwise, if \tcode{T} is an array type\iref{term.array.type} and
  \tcode{remove_all_extents_t<T>} is an incomplete type,
  \tcode{ranges::data(E)} is ill-formed with no diagnostic required.

\item
  Otherwise, if \tcode{auto(t.data())}
  is a valid expression of pointer to object type,
  \tcode{ranges::data(E)} is expression-equivalent to
  \tcode{auto(t.data())}.

\item
  Otherwise, if \tcode{ranges::begin(t)}
  is a valid expression whose type models
  \libconcept{contiguous_iterator},
  \tcode{ranges::data(E)} is expression-equivalent to
  \tcode{to_address(ranges::begin(t))}.

\item
  Otherwise, \tcode{ranges::data(E)} is ill-formed.
\end{itemize}

\pnum
\begin{note}
Diagnosable ill-formed cases above
result in substitution failure when \tcode{ranges::data(E)}
appears in the immediate context of a template instantiation.
\end{note}

\pnum
\begin{note}
Whenever \tcode{ranges::data(E)} is a valid expression, it
has pointer to object type.
\end{note}

\rSec2[range.prim.cdata]{\tcode{ranges::cdata}}
\indexlibraryglobal{cdata}%

\begin{codeblock}
template<class T>
constexpr auto @\exposid{as-const-pointer}@(const T* p) noexcept { return p; }  // \expos
\end{codeblock}

\pnum
The name \tcode{ranges::cdata} denotes a customization point
object\iref{customization.point.object}.
Given a subexpression \tcode{E} with type \tcode{T},
let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}.
Then:
\begin{itemize}
\item
If \tcode{E} is an rvalue and
\tcode{enable_borrowed_range<remove_cv_t<T>>} is \tcode{false},
\tcode{ranges::cdata(E)} is ill-formed.
\item
Otherwise,
\tcode{ranges::cdata(E)} is expression-equivalent to
\tcode{\exposid{as-const-pointer}(ranges::data(\exposid{possi\-bly-const-range}(t)))}.
\end{itemize}

\pnum
\begin{note}
Whenever \tcode{ranges::cdata(E)} is a valid expression, it
has pointer to constant object type.
\end{note}

\rSec1[range.req]{Range requirements}

\rSec2[range.req.general]{General}

\pnum
Ranges are an abstraction that allows a \Cpp{} program
to operate on elements of data structures uniformly.
Calling \tcode{ranges::begin} on a range returns an object
whose type models \libconcept{input_or_output_iterator}\iref{iterator.concept.iterator}.
Calling \tcode{ranges::end} on a range returns an object whose type \tcode{S},
together with the type \tcode{I} of the object returned by \tcode{ranges::begin},
models \tcode{\libconcept{sentinel_for}<S, I>}.
The library formalizes the interfaces, semantics, and complexity of ranges
to enable algorithms and range adaptors that work efficiently
on different types of sequences.

\pnum
The \libconcept{range} concept requires that
\tcode{ranges::begin} and \tcode{ranges::end}
return an iterator and a sentinel, respectively.
The \libconcept{sized_range} concept refines \libconcept{range} with
the requirement that \tcode{ranges::size} be amortized \bigoh{1}.
The \libconcept{view} concept specifies requirements on
a \libconcept{range} type to provide operations with predictable complexity.

\pnum
Several refinements of \libconcept{range} group requirements
that arise frequently in concepts and algorithms.
Common ranges are ranges for which
\tcode{ranges::begin} and \tcode{ranges::end}
return objects of the same type.
Random access ranges are ranges for which \tcode{ranges::begin}
returns a type that models
\libconcept{random_access_iterator}\iref{iterator.concept.random.access}.
(Contiguous, bidirectional, forward, input, and output ranges
are defined similarly.)
Viewable ranges can be converted to views.

\rSec2[range.range]{Ranges}

\pnum
The \libconcept{range} concept defines the requirements of a type that allows
iteration over its elements by providing an iterator and sentinel
that denote the elements of the range.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{range}@ =
    requires(T& t) {
      ranges::begin(t);         // sometimes equality-preserving (see below)
      ranges::end(t);
    };
\end{itemdecl}

\begin{itemdescr}
\pnum
Given an expression \tcode{t} such that \tcode{decltype((t))} is \tcode{T\&},
\tcode{T} models \libconcept{range} only if
\begin{itemize}
\item \range{ranges::begin(t)}{ranges::end(t)}
  denotes a range\iref{iterator.requirements.general},

\item both
\tcode{ranges::begin(t)}
and
\tcode{ranges::end(t)}
are amortized constant time and non-modifying, and

\item if the type of \tcode{ranges::begin(t)} models
\libconcept{forward_iterator}, \tcode{ranges::begin(t)} is equality-preserving.
\end{itemize}

\pnum
\begin{note}
Equality preservation of both \tcode{ranges::begin} and
\tcode{ranges::end} enables passing a range whose iterator
type models \libconcept{forward_iterator} to multiple
algorithms and making multiple passes over the range by repeated calls to
\tcode{ranges::begin} and \tcode{ranges::end}.
Since \tcode{ranges::begin} is not required to be equality-preserving
when the return type does not model \libconcept{forward_iterator},
it is possible for repeated calls
to not return equal values or to not be well-defined.
\end{note}
\end{itemdescr}

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{borrowed_range}@ =
    @\libconcept{range}@<T> && (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{U} be \tcode{remove_reference_t<T>}
if \tcode{T} is an rvalue reference type, and \tcode{T} otherwise.
Given a variable \tcode{u} of type \tcode{U},
\tcode{T} models \libconcept{borrowed_range} only if
the validity of iterators obtained from \tcode{u}
is not tied to the lifetime of that variable.

\pnum
\begin{note}
Since the validity of iterators is not tied to the lifetime of
a variable whose type models \libconcept{borrowed_range},
a function with a parameter of such a type can
return iterators obtained from it without danger of dangling.
\end{note}
\end{itemdescr}

\indexlibraryglobal{enable_borrowed_range}%
\begin{itemdecl}
template<class>
  constexpr bool enable_borrowed_range = false;
\end{itemdecl}

\begin{itemdescr}
\pnum
\remarks
Pursuant to \ref{namespace.std}, users may specialize \tcode{enable_borrowed_range}
for cv-unqualified program-defined types.
Such specializations shall be
usable in constant expressions\iref{expr.const.init} and
have type \tcode{const bool}.

\pnum
\begin{example}
Each specialization \tcode{S} of class template \tcode{subrange}\iref{range.subrange}
models \libconcept{borrowed_range} because
\begin{itemize}
\item
\tcode{enable_borrowed_range<S>} is specialized
to have the value \tcode{true}, and

\item
\tcode{S}'s iterators
do not have validity tied to the lifetime of an \tcode{S} object
because they are ``borrowed'' from some other range.
\end{itemize}
\end{example}
\end{itemdescr}

\rSec2[range.approximately.sized]{Approximately sized ranges}

\pnum
The \libconcept{approximately_sized_range} concept refines \libconcept{range}
with the requirement that
an approximation of the number of elements in the range
can be determined in amortized constant time using \tcode{ranges::reserve_hint}.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{approximately_sized_range}@ =
    @\libconcept{range}@<T> && requires(T& t) { ranges::reserve_hint(t); };
\end{itemdecl}

\begin{itemdescr}
\pnum
Given an lvalue \tcode{t} of type \tcode{remove_reference_t<T>},
\tcode{T} models \libconcept{approximately_sized_range} only if
\begin{itemize}
\item
\tcode{ranges::reserve_hint(t)} is amortized \bigoh{1},
does not modify \tcode{t}, and
has a value that
is not negative and is representable in \tcode{range_difference_t<T>}, and
\item
if \tcode{iterator_t<T>} models \libconcept{forward_iterator},
\tcode{ranges::reserve_hint(t)} is well-defined
regardless of the evaluation of \tcode{ranges::begin(t)}.
\begin{note}
\tcode{ranges::reserve_hint(t)} is otherwise not required to be well-defined
after evaluating \tcode{ranges::\linebreak begin(t)}.
For example,
it is possible for \tcode{ranges::reserve_hint(t)} to be well-defined for
an \libconceptx{approximate\-ly_sized_range}{approximately_sized_range} whose
iterator type does not model \libconcept{forward_iterator}
only if evaluated before the first call to \tcode{ranges::begin(t)}.
\end{note}
\end{itemize}
\end{itemdescr}

\rSec2[range.sized]{Sized ranges}

\pnum
The \libconcept{sized_range} concept
refines \libconcept{approximately_sized_range} with
the requirement that the number of elements in the range can be determined
in amortized constant time using \tcode{ranges::size}.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{sized_range}@ =
    @\libconcept{approximately_sized_range}@<T> && requires(T& t) { ranges::size(t); };
\end{itemdecl}

\begin{itemdescr}
\pnum
Given an lvalue \tcode{t} of type \tcode{remove_reference_t<T>}, \tcode{T}
models \libconcept{sized_range} only if
\begin{itemize}
\item \tcode{ranges::size(t)} is amortized \bigoh{1}, does not modify \tcode{t},
and is equal to \tcode{ranges::distance(\brk{}ranges::begin(t), ranges::end(t))}, and

\item if \tcode{iterator_t<T>} models \libconcept{forward_iterator},
\tcode{ranges::size(t)} is well-defined regardless of the evaluation of
\tcode{ranges::begin(t)}.
\begin{note}
\tcode{ranges::size(t)} is otherwise not required to be
well-defined after evaluating \tcode{ranges::begin(t)}.
For example, it is possible for \tcode{ranges::size(t)} to be well-defined
for a \libconcept{sized_range} whose iterator type
does not model \libconcept{forward_iterator}
only if evaluated before the first call to \tcode{ranges::begin(t)}.
\end{note}
\end{itemize}
\end{itemdescr}

\indexlibraryglobal{disable_sized_range}%
\begin{itemdecl}
template<class>
  constexpr bool disable_sized_range = false;
\end{itemdecl}

\begin{itemdescr}
\pnum
\remarks
Pursuant to \ref{namespace.std},
users may specialize \tcode{disable_sized_range}
for cv-unqualified program-defined types.
Such specializations shall
be usable in constant expressions\iref{expr.const.init} and
have type \tcode{const bool}.

\pnum
\begin{note}
\tcode{disable_sized_range} allows use of \libconcept{range} types with the library
that satisfy but do not in fact model \libconcept{sized_range}.
\end{note}
\end{itemdescr}

\rSec2[range.view]{Views}

\pnum
The \libconcept{view} concept specifies the requirements of a \libconcept{range} type
that has the semantic properties below,
which make it suitable for use in
constructing range adaptor pipelines\iref{range.adaptors}.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{view}@ =
    @\libconcept{range}@<T> && @\libconcept{movable}@<T> && enable_view<T>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{T} models \libconcept{view} only if
\begin{itemize}
\item
\tcode{T} has \bigoh{1} move construction; and

\item
move assignment of an object of type \tcode{T}
is no more complex than destruction followed by move construction; and

\item
if $N$ copies and/or moves are made from an object of type \tcode{T}
that contained $M$ elements,
then those $N$ objects have \bigoh{N+M} destruction; and

\item
\tcode{\libconcept{copy_constructible}<T>} is \tcode{false}, or
\tcode{T} has \bigoh{1} copy construction; and

\item
\tcode{\libconcept{copyable}<T>} is \tcode{false}, or
copy assignment of an object of type \tcode{T}
is no more complex than destruction followed by copy construction.
\end{itemize}

\pnum
\begin{note}
The constraints on copying and moving imply that
a moved-from object of type \tcode{T} has \bigoh{1} destruction.
\end{note}

\pnum
\begin{example}
Examples of views are:
\begin{itemize}
\item A \libconcept{range} type that wraps a pair of iterators.

\item A \libconcept{range} type that holds its elements by \tcode{shared_ptr}
and shares ownership with all its copies.

\item A \libconcept{range} type that generates its elements on demand.
\end{itemize}

A container such as \tcode{vector<string>}
does not meet the semantic requirements of \libconcept{view}
since copying the container copies all of the elements,
which cannot be done in constant time.
\end{example}
\end{itemdescr}

\pnum
Since the difference between \libconcept{range} and \libconcept{view} is largely
semantic, the two are differentiated with the help of \tcode{enable_view}.

\indexlibraryglobal{enable_view}%
\begin{itemdecl}
template<class T>
  constexpr bool @\exposidnc{is-derived-from-view-interface}@ = @\seebelownc@;            // \expos
template<class T>
  constexpr bool enable_view =
    @\libconcept{derived_from}@<T, view_base> || @\exposid{is-derived-from-view-interface}@<T>;
\end{itemdecl}

\begin{itemdescr}
\pnum
For a type \tcode{T},
\tcode{\exposid{is-derived-from-view-interface}<T>} is \tcode{true}
if and only if
\tcode{T} has exactly one public base class \tcode{view_interface<U>}
for some type \tcode{U} and
\tcode{T} has no base classes of type \tcode{view_interface<V>}
for any other type \tcode{V}.

\pnum
\remarks
Pursuant to \ref{namespace.std}, users may specialize \tcode{enable_view}
to \tcode{true}
for cv-unqualified program-defined types that model \libconcept{view},
and \tcode{false} for types that do not.
Such specializations shall
be usable in constant expressions\iref{expr.const.init} and
have type \tcode{const bool}.
\end{itemdescr}

\rSec2[range.refinements]{Other range refinements}

\pnum
The \libconcept{output_range} concept specifies requirements of a
\libconcept{range} type for which \tcode{ranges::begin} returns
a model of \libconcept{output_iterator}\iref{iterator.concept.output}.
\libconcept{input_range}, \libconcept{forward_range}, \libconcept{bidirectional_range},
and \libconcept{random_access_range} are defined similarly.

\begin{itemdecl}
template<class R, class T>
  concept @\deflibconcept{output_range}@ =
    @\libconcept{range}@<R> && @\libconcept{output_iterator}@<iterator_t<R>, T>;

template<class T>
  concept @\deflibconcept{input_range}@ =
    @\libconcept{range}@<T> && @\libconcept{input_iterator}@<iterator_t<T>>;

template<class T>
  concept @\deflibconcept{forward_range}@ =
    @\libconcept{input_range}@<T> && @\libconcept{forward_iterator}@<iterator_t<T>>;

template<class T>
  concept @\deflibconcept{bidirectional_range}@ =
    @\libconcept{forward_range}@<T> && @\libconcept{bidirectional_iterator}@<iterator_t<T>>;

template<class T>
  concept @\deflibconcept{random_access_range}@ =
    @\libconcept{bidirectional_range}@<T> && @\libconcept{random_access_iterator}@<iterator_t<T>>;
\end{itemdecl}

\pnum
\libconcept{contiguous_range} additionally requires that
the \tcode{ranges::data} customization point object\iref{range.prim.data}
is usable with the range.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{contiguous_range}@ =
    @\libconcept{random_access_range}@<T> && @\libconcept{contiguous_iterator}@<iterator_t<T>> &&
    requires(T& t) {
      { ranges::data(t) } -> @\libconcept{same_as}@<add_pointer_t<range_reference_t<T>>>;
    };
\end{itemdecl}

\pnum
Given an expression \tcode{t} such that \tcode{decltype((t))} is \tcode{T\&},
\tcode{T} models \libconcept{contiguous_range} only if
\tcode{to_address(\brk{}ranges::begin(t)) == ranges::data(t)}
is \tcode{true}.

\pnum
The \libconcept{common_range} concept specifies requirements of
a \libconcept{range} type for which \tcode{ranges::begin} and
\tcode{ranges::end} return objects of the same type.
\begin{example}
The standard containers\iref{containers} model \libconcept{common_range}.
\end{example}

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{common_range}@ =
    @\libconcept{range}@<T> && @\libconcept{same_as}@<iterator_t<T>, sentinel_t<T>>;
\end{itemdecl}

\begin{itemdecl}
template<class R>
  constexpr bool @\exposidnc{is-initializer-list}@ = @\seebelow@;               // \expos
\end{itemdecl}

\begin{itemdescr}
\pnum
For a type \tcode{R},
\tcode{\exposid{is-initializer-list}<R>} is \tcode{true} if and only if
\tcode{remove_cvref_t<R>} is a specialization of \tcode{initializer_list}.
\end{itemdescr}

\pnum
The \libconcept{viewable_range} concept specifies the requirements of a
\libconcept{range} type that can be converted to a view safely.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{viewable_range}@ =
    @\libconcept{range}@<T> &&
    ((@\libconcept{view}@<remove_cvref_t<T>> && @\libconcept{constructible_from}@<remove_cvref_t<T>, T>) ||
     (!@\libconcept{view}@<remove_cvref_t<T>> &&
      (is_lvalue_reference_v<T> || (@\libconcept{movable}@<remove_reference_t<T>> && !@\exposid{is-initializer-list}@<T>))));
\end{itemdecl}

\pnum
The \libconcept{constant_range} concept specifies the requirements of a
\libconcept{range} type whose elements are not modifiable.

\begin{itemdecl}
template<class T>
  concept @\deflibconcept{constant_range}@ =
    @\libconcept{input_range}@<T> && @\exposconcept{constant-iterator}@<iterator_t<T>>;
\end{itemdecl}

\pnum
The exposition-only concept \exposconcept{sized-random-access-range}
specifies the requirements of a \libconcept{range} type
that is sized and allows random access to its elements.

\begin{itemdecl}
template<class T>
  concept @\defexposconcept{sized-random-access-range}@ =           // \expos
    @\libconcept{random_access_range}@<T> && @\libconcept{sized_range}@<T>;
\end{itemdecl}
\begin{note}
This concept constrains some parallel algorithm overloads;
see \ref{algorithms}.
\end{note}

\rSec1[range.utility]{Range utilities}

\rSec2[range.utility.general]{General}

\pnum
The components in \ref{range.utility} are general utilities for representing and
manipulating ranges.

\rSec2[range.utility.helpers]{Helper concepts}

\pnum
Many of the types in \ref{range.utility} are specified in terms of
the following exposition-only concepts:

\begin{codeblock}
template<class R>
  concept @\defexposconceptnc{simple-view}@ =                                     // \expos
    @\libconcept{view}@<R> && @\libconcept{range}@<const R> &&
    @\libconcept{same_as}@<iterator_t<R>, iterator_t<const R>> &&
    @\libconcept{same_as}@<sentinel_t<R>, sentinel_t<const R>>;

template<class I>
  concept @\defexposconceptnc{has-arrow}@ =                                       // \expos
    @\libconcept{input_iterator}@<I> && (is_pointer_v<I> || requires(const I i) { i.operator->(); });

template<class T, class U>
  concept @\defexposconceptnc{different-from}@ =                                  // \expos
    !@\libconcept{same_as}@<remove_cvref_t<T>, remove_cvref_t<U>>;

template<class R>
  concept @\defexposconceptnc{range-with-movable-references}@ =                   // \expos
    @\libconcept{input_range}@<R> && @\libconcept{move_constructible}@<range_reference_t<R>> &&
    @\libconcept{move_constructible}@<range_rvalue_reference_t<R>>;
\end{codeblock}

\rSec2[view.interface]{View interface}

\rSec3[view.interface.general]{General}

\pnum
The class template \tcode{view_interface} is a helper for defining
view-like types that offer a container-like interface. It is
parameterized with the type that is derived from it.

\indexlibraryglobal{view_interface}%
\begin{codeblock}
namespace std::ranges {
  template<class D>
    requires is_class_v<D> && @\libconcept{same_as}@<D, remove_cv_t<D>>
  class view_interface {
  private:
    constexpr D& @\exposidnc{derived}@() noexcept {               // \expos
      return static_cast<D&>(*this);
    }
    constexpr const D& @\exposidnc{derived}@() const noexcept {   // \expos
      return static_cast<const D&>(*this);
    }

  public:
    constexpr bool empty() requires @\libconcept{sized_range}@<D> || @\libconcept{forward_range}@<D> {
      if constexpr (@\libconcept{sized_range}@<D>)
        return ranges::size(@\exposid{derived}@()) == 0;
      else
        return ranges::begin(@\exposid{derived}@()) == ranges::end(@\exposid{derived}@());
    }
    constexpr bool empty() const requires @\libconcept{sized_range}@<const D> || @\libconcept{forward_range}@<const D> {
      if constexpr (@\libconcept{sized_range}@<const D>)
        return ranges::size(@\exposid{derived}@()) == 0;
      else
        return ranges::begin(@\exposid{derived}@()) == ranges::end(@\exposid{derived}@());
    }

    constexpr auto cbegin() requires @\libconcept{input_range}@<D> {
      return ranges::cbegin(@\exposid{derived}@());
    }
    constexpr auto cbegin() const requires @\libconcept{input_range}@<const D> {
      return ranges::cbegin(@\exposid{derived}@());
    }
    constexpr auto cend() requires @\libconcept{input_range}@<D> {
      return ranges::cend(@\exposid{derived}@());
    }
    constexpr auto cend() const requires @\libconcept{input_range}@<const D> {
      return ranges::cend(@\exposid{derived}@());
    }

    constexpr explicit operator bool()
      requires requires { ranges::empty(@\exposid{derived}@()); } {
        return !ranges::empty(@\exposid{derived}@());
      }
    constexpr explicit operator bool() const
      requires requires { ranges::empty(@\exposid{derived}@()); } {
        return !ranges::empty(@\exposid{derived}@());
      }

    constexpr auto data() requires @\libconcept{contiguous_iterator}@<iterator_t<D>> {
      return to_address(ranges::begin(@\exposid{derived}@()));
    }
    constexpr auto data() const
      requires @\libconcept{range}@<const D> && @\libconcept{contiguous_iterator}@<iterator_t<const D>> {
        return to_address(ranges::begin(@\exposid{derived}@()));
      }

    constexpr auto size() requires @\libconcept{forward_range}@<D> &&
      @\libconcept{sized_sentinel_for}@<sentinel_t<D>, iterator_t<D>> {
        return @\exposid{to-unsigned-like}@(ranges::end(@\exposid{derived}@()) - ranges::begin(@\exposid{derived}@()));
      }
    constexpr auto size() const requires @\libconcept{forward_range}@<const D> &&
      @\libconcept{sized_sentinel_for}@<sentinel_t<const D>, iterator_t<const D>> {
        return @\exposid{to-unsigned-like}@(ranges::end(@\exposid{derived}@()) - ranges::begin(@\exposid{derived}@()));
      }

    constexpr decltype(auto) front() requires @\libconcept{forward_range}@<D>;
    constexpr decltype(auto) front() const requires @\libconcept{forward_range}@<const D>;

    constexpr decltype(auto) back() requires @\libconcept{bidirectional_range}@<D> && @\libconcept{common_range}@<D>;
    constexpr decltype(auto) back() const
      requires @\libconcept{bidirectional_range}@<const D> && @\libconcept{common_range}@<const D>;

    template<@\libconcept{random_access_range}@ R = D>
      constexpr decltype(auto) operator[](range_difference_t<R> n) {
        return ranges::begin(@\exposid{derived}@())[n];
      }
    template<@\libconcept{random_access_range}@ R = const D>
      constexpr decltype(auto) operator[](range_difference_t<R> n) const {
        return ranges::begin(@\exposid{derived}@())[n];
      }
  };
}
\end{codeblock}

\pnum
The template parameter \tcode{D} for \tcode{view_interface} may be an
incomplete type. Before any member of the resulting specialization of
\tcode{view_interface} other than special member functions
is referenced, \tcode{D} shall be complete, and
model both \tcode{\libconcept{derived_from}<view_interface<D>>} and \libconcept{view}.

\rSec3[view.interface.members]{Members}

\indexlibrarymember{front}{view_interface}%
\begin{itemdecl}
constexpr decltype(auto) front() requires @\libconcept{forward_range}@<D>;
constexpr decltype(auto) front() const requires @\libconcept{forward_range}@<const D>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{!empty()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return *ranges::begin(\exposid{derived}());}
\end{itemdescr}

\indexlibrarymember{back}{view_interface}%
\begin{itemdecl}
constexpr decltype(auto) back() requires @\libconcept{bidirectional_range}@<D> && @\libconcept{common_range}@<D>;
constexpr decltype(auto) back() const
  requires @\libconcept{bidirectional_range}@<const D> && @\libconcept{common_range}@<const D>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{!empty()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return *ranges::prev(ranges::end(\exposid{derived}()));}
\end{itemdescr}

\rSec2[range.subrange]{Sub-ranges}

\rSec3[range.subrange.general]{General}

\pnum
The \tcode{subrange} class template combines together an
iterator and a sentinel into a single object that models the
\libconcept{view} concept. Additionally, it models the
\libconcept{sized_range} concept when the final template parameter is
\tcode{subrange_kind::sized}.

\indexlibraryglobal{subrange}%
\begin{codeblock}
namespace std::ranges {
  template<class From, class To>
    concept @\defexposconceptnc{uses-nonqualification-pointer-conversion}@ =      // \expos
      is_pointer_v<From> && is_pointer_v<To> &&
      !@\libconcept{convertible_to}@<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>;

  template<class From, class To>
    concept @\defexposconceptnc{convertible-to-non-slicing}@ =                    // \expos
      @\libconcept{convertible_to}@<From, To> &&
      !@\exposconcept{uses-nonqualification-pointer-conversion}@<decay_t<From>, decay_t<To>>;

  template<class T, class U, class V>
    concept @\defexposconceptnc{pair-like-convertible-from}@ =                    // \expos
      !@\libconcept{range}@<T> && !is_reference_v<T> && @\exposconcept{pair-like}@<T> &&
      @\libconcept{constructible_from}@<T, U, V> &&
      @\exposconcept{convertible-to-non-slicing}@<U, tuple_element_t<0, T>> &&
      @\libconcept{convertible_to}@<V, tuple_element_t<1, T>>;

  template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@<I> S = I, subrange_kind K =
      @\libconcept{sized_sentinel_for}@<S, I> ? subrange_kind::sized : subrange_kind::unsized>
    requires (K == subrange_kind::sized || !@\libconcept{sized_sentinel_for}@<S, I>)
  class subrange : public view_interface<subrange<I, S, K>> {
  private:
    static constexpr bool @\exposidnc{StoreSize}@ =                       // \expos
      K == subrange_kind::sized && !@\libconcept{sized_sentinel_for}@<S, I>;
    I @\exposid{begin_}@ = I();                                         // \expos
    S @\exposid{end_}@ = S();                                           // \expos
    @\exposidnc{make-unsigned-like-t}@<iter_difference_t<I>> @\exposid{size_}@ = 0;   // \expos; present only
                                                            // if \exposid{StoreSize} is \tcode{true}
  public:
    subrange() requires @\libconcept{default_initializable}@<I> = default;

    constexpr subrange(@\exposconcept{convertible-to-non-slicing}@<I> auto i, S s) requires (!@\exposid{StoreSize}@);

    constexpr subrange(@\exposconcept{convertible-to-non-slicing}@<I> auto i, S s,
                       @\placeholdernc{make-unsigned-like-t}@<iter_difference_t<I>> n)
      requires (K == subrange_kind::sized);

    template<@\exposconcept{different-from}@<subrange> R>
      requires @\libconcept{borrowed_range}@<R> &&
               @\exposconcept{convertible-to-non-slicing}@<iterator_t<R>, I> &&
               @\libconcept{convertible_to}@<sentinel_t<R>, S>
    constexpr subrange(R&& r) requires (!@\exposid{StoreSize}@ || @\libconcept{sized_range}@<R>);

    template<@\libconcept{borrowed_range}@ R>
      requires @\exposconcept{convertible-to-non-slicing}@<iterator_t<R>, I> &&
               @\libconcept{convertible_to}@<sentinel_t<R>, S>
    constexpr subrange(R&& r, @\placeholdernc{make-unsigned-like-t}@<iter_difference_t<I>> n)
      requires (K == subrange_kind::sized)
        : subrange{ranges::begin(r), ranges::end(r), n} {}

    template<@\exposconcept{different-from}@<subrange> PairLike>
      requires @\exposconcept{pair-like-convertible-from}@<PairLike, const I&, const S&>
    constexpr operator PairLike() const;

    constexpr I begin() const requires @\libconcept{copyable}@<I>;
    constexpr I begin() requires (!@\libconcept{copyable}@<I>);
    constexpr S end() const;

    constexpr bool empty() const;
    constexpr @\placeholdernc{make-unsigned-like-t}@<iter_difference_t<I>> size() const
      requires (K == subrange_kind::sized);

    constexpr subrange next(iter_difference_t<I> n = 1) const &
      requires @\libconcept{forward_iterator}@<I>;
    constexpr subrange next(iter_difference_t<I> n = 1) &&;
    constexpr subrange prev(iter_difference_t<I> n = 1) const
      requires @\libconcept{bidirectional_iterator}@<I>;
    constexpr subrange& advance(iter_difference_t<I> n);
  };

  template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@<I> S>
    subrange(I, S) -> subrange<I, S>;

  template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@<I> S>
    subrange(I, S, @\placeholdernc{make-unsigned-like-t}@<iter_difference_t<I>>) ->
      subrange<I, S, subrange_kind::sized>;

  template<@\libconcept{borrowed_range}@ R>
    subrange(R&&) ->
      subrange<iterator_t<R>, sentinel_t<R>,
               (@\libconcept{sized_range}@<R> || @\libconcept{sized_sentinel_for}@<sentinel_t<R>, iterator_t<R>>)
                 ? subrange_kind::sized : subrange_kind::unsized>;

  template<@\libconcept{borrowed_range}@ R>
    subrange(R&&, @\placeholdernc{make-unsigned-like-t}@<range_difference_t<R>>) ->
      subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
}
\end{codeblock}

\rSec3[range.subrange.ctor]{Constructors and conversions}

\indexlibraryctor{subrange}%
\begin{itemdecl}
constexpr subrange(@\exposconcept{convertible-to-non-slicing}@<I> auto i, S s) requires (!@\exposid{StoreSize}@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{i}{s} is a valid range.

\pnum
\effects
Initializes \exposid{begin_} with \tcode{std::move(i)} and \exposid{end_} with
\tcode{s}.
\end{itemdescr}

\indexlibraryctor{subrange}%
\begin{itemdecl}
constexpr subrange(@\exposconcept{convertible-to-non-slicing}@<I> auto i, S s,
                   @\placeholdernc{make-unsigned-like-t}@<iter_difference_t<I>> n)
  requires (K == subrange_kind::sized);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{i}{s} is a valid range, and
\tcode{n == \placeholdernc{to-unsigned-like}(ranges::distance(i, s))}
is \tcode{true}.

\pnum
\effects
Initializes \exposid{begin_} with \tcode{std::move(i)} and \exposid{end_} with
\tcode{s}. If \exposid{StoreSize} is \tcode{true}, initializes \exposid{size_} with
\tcode{n}.

\pnum
\begin{note}
Accepting the length of the range and storing it to later return  from
\tcode{size()} enables \tcode{subrange} to model \libconcept{sized_range} even
when it stores an iterator and sentinel that do not model
\libconcept{sized_sentinel_for}.
\end{note}
\end{itemdescr}

\indexlibraryctor{subrange}%
\begin{itemdecl}
template<@\exposconcept{different-from}@<subrange> R>
  requires @\libconcept{borrowed_range}@<R> &&
           @\exposconcept{convertible-to-non-slicing}@<iterator_t<R>, I> &&
           @\libconcept{convertible_to}@<sentinel_t<R>, S>
constexpr subrange(R&& r) requires (!@\exposid{StoreSize}@ || @\libconcept{sized_range}@<R>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{itemize}
\item If \exposid{StoreSize} is \tcode{true},
\tcode{subrange(r, static_cast<decltype(\exposid{size_})>(ranges::size(r)))}.
\item Otherwise, \tcode{subrange(ranges::begin(r), ranges::end(r))}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator \placeholder{PairLike}}{subrange}%
\begin{itemdecl}
template<@\exposconcept{different-from}@<subrange> PairLike>
  requires @\exposconcept{pair-like-convertible-from}@<PairLike, const I&, const S&>
constexpr operator PairLike() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return PairLike(\exposid{begin_}, \exposid{end_});}
\end{itemdescr}

\rSec3[range.subrange.access]{Accessors}

\indexlibrarymember{begin}{subrange}%
\begin{itemdecl}
constexpr I begin() const requires @\libconcept{copyable}@<I>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{begin_};}
\end{itemdescr}

\indexlibrarymember{begin}{subrange}%
\begin{itemdecl}
constexpr I begin() requires (!@\libconcept{copyable}@<I>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return std::move(\exposid{begin_});}
\end{itemdescr}

\indexlibrarymember{end}{subrange}%
\begin{itemdecl}
constexpr S end() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{empty}{subrange}%
\begin{itemdecl}
constexpr bool empty() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{begin_} == \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{size}{subrange}%
\begin{itemdecl}
constexpr @\placeholdernc{make-unsigned-like-t}@<iter_difference_t<I>> size() const
  requires (K == subrange_kind::sized);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\begin{itemize}
\item If \exposid{StoreSize} is \tcode{true}, equivalent to: \tcode{return \exposid{size_};}
\item Otherwise, equivalent to: \tcode{return \placeholdernc{to-unsigned-like}(\exposid{end_} - \exposid{begin_});}
\end{itemize}
\end{itemdescr}

\indexlibrarymember{next}{subrange}%
\begin{itemdecl}
constexpr subrange next(iter_difference_t<I> n = 1) const &
  requires @\libconcept{forward_iterator}@<I>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
tmp.advance(n);
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{next}{subrange}%
\begin{itemdecl}
constexpr subrange next(iter_difference_t<I> n = 1) &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
advance(n);
return std::move(*this);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{prev}{subrange}%
\begin{itemdecl}
constexpr subrange prev(iter_difference_t<I> n = 1) const
  requires @\libconcept{bidirectional_iterator}@<I>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
tmp.advance(-n);
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{advance}{subrange}%
\begin{itemdecl}
constexpr subrange& advance(iter_difference_t<I> n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\libconcept{bidirectional_iterator}@<I>) {
  if (n < 0) {
    ranges::advance(@\exposid{begin_}@, n);
    if constexpr (@\exposid{StoreSize}@)
      @\exposid{size_}@ += @\placeholdernc{to-unsigned-like}@(-n);
    return *this;
  }
}

auto d = n - ranges::advance(@\exposid{begin_}@, n, @\exposid{end_}@);
if constexpr (@\exposid{StoreSize}@)
  @\exposid{size_}@ -= @\placeholdernc{to-unsigned-like}@(d);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{get}{subrange}%
\begin{itemdecl}
template<size_t N, class I, class S, subrange_kind K>
  requires ((N == 0 && @\libconcept{copyable}@<I>) || N == 1)
  constexpr auto get(const subrange<I, S, K>& r);
template<size_t N, class I, class S, subrange_kind K>
  requires (N < 2)
  constexpr auto get(subrange<I, S, K>&& r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (N == 0)
  return r.begin();
else
  return r.end();
\end{codeblock}
\end{itemdescr}

\rSec2[range.dangling]{Dangling iterator handling}

\pnum
The type \tcode{dangling} is used together with the template aliases
\tcode{borrowed_iterator_t} and \tcode{borrowed_subrange_t}.
When an algorithm
that typically returns an iterator into, or a subrange of, a range argument
is called with an rvalue range argument
that does not model \libconcept{borrowed_range}\iref{range.range},
the return value possibly refers to a range whose lifetime has ended.
In such cases,
the type \tcode{dangling} is returned instead of an iterator or subrange.
\indexlibraryglobal{dangling}%
\begin{codeblock}
namespace std::ranges {
  struct dangling {
    constexpr dangling() noexcept = default;
    constexpr dangling(auto&&...) noexcept {}
  };
}
\end{codeblock}

\pnum
\begin{example}
\begin{codeblock}
vector<int> f();
auto result1 = ranges::find(f(), 42);                                   // \#1
static_assert(@\libconcept{same_as}@<decltype(result1), ranges::dangling>);
auto vec = f();
auto result2 = ranges::find(vec, 42);                                   // \#2
static_assert(@\libconcept{same_as}@<decltype(result2), vector<int>::iterator>);
auto result3 = ranges::find(ranges::subrange{vec}, 42);                 // \#3
static_assert(@\libconcept{same_as}@<decltype(result3), vector<int>::iterator>);
\end{codeblock}
The call to \tcode{ranges::find} at \#1 returns \tcode{ranges::dangling}
since \tcode{f()} is an rvalue \tcode{vector};
it is possible for the \tcode{vector} to be destroyed
before a returned iterator is dereferenced.
However, the calls at \#2 and \#3 both return iterators
since the lvalue \tcode{vec} and specializations of \tcode{subrange}
model \libconcept{borrowed_range}.
\end{example}

\indexlibraryglobal{borrowed_iterator_t}%
\indexlibraryglobal{borrowed_subrange_t}%
\pnum
For a type \tcode{R} that models \libconcept{range}:
\begin{itemize}
\item
if \tcode{R} models \libconcept{borrowed_range}, then
\tcode{borrowed_iterator_t<R>} denotes \tcode{iterator_t<R>}, and
\tcode{borrowed_subrange_t<R>} denotes \tcode{subrange<iterator_t<R>>};
\item
otherwise,
both \tcode{borrowed_iterator_t<R>} and \tcode{borrowed_subrange_t<R>}
denote \tcode{dangling}.
\end{itemize}

\rSec2[range.elementsof]{Class template \tcode{elements_of}}

Specializations of \tcode{elements_of} encapsulate a range and
act as a tag in overload sets to disambiguate
when a range should be treated as a sequence
rather than a single value.

\begin{example}
\begin{codeblock}
template<bool YieldElements>
generator<any> f(ranges::@\libconcept{input_range}@ auto&& r) {
  if constexpr (YieldElements)
    co_yield ranges::elements_of(r);        // yield each element of \tcode{r}
  else
    co_yield r;                             // yield \tcode{r} as a single value
}
\end{codeblock}
\end{example}

\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{range}@ R, class Allocator = allocator<byte>>
  struct elements_of {
    [[no_unique_address]] R range;
    [[no_unique_address]] Allocator allocator = Allocator();
  };

  template<class R, class Allocator = allocator<byte>>
    elements_of(R&&, Allocator = Allocator()) -> elements_of<R&&, Allocator>;
}
\end{codeblock}

\rSec2[range.utility.conv]{Range conversions}

\rSec3[range.utility.conv.general]{General}

\pnum
The range conversion functions construct
an object (usually a container) from a range,
by using a constructor taking a range,
a \tcode{from_range_t} tagged constructor, or
a constructor taking a pair of iterators, or
by inserting each element of the range into the default-constructed object.

\pnum
\tcode{ranges::to} is applied recursively,
allowing the conversion of a range of ranges.

\begin{example}
\begin{codeblock}
string_view str = "the quick brown fox";
auto words = views::split(str, ' ') | to<vector<string>>();
// \tcode{words} is \tcode{vector<string>\{"the", "quick", "brown", "fox"\}}
\end{codeblock}
\end{example}

\pnum
Let \exposid{reservable-container} be defined as follows:
\begin{codeblock}
template<class Container>
constexpr bool @\exposid{reservable-container}@ =          // \expos
  @\libconcept{sized_range}@<Container> &&
  requires(Container& c, range_size_t<Container> n) {
    c.reserve(n);
    { c.capacity() } -> @\libconcept{same_as}@<decltype(n)>;
    { c.max_size() } -> @\libconcept{same_as}@<decltype(n)>;
  };
\end{codeblock}

\pnum
Let \exposid{container-appendable} be defined as follows:
\begin{codeblock}
template<class Container, class Ref>
constexpr bool @\exposid{container-appendable}@ =          // \expos
  requires(Container& c, Ref&& ref) {
    requires (requires { c.emplace_back(std::forward<Ref>(ref)); } ||
              requires { c.push_back(std::forward<Ref>(ref)); } ||
              requires { c.emplace(c.end(), std::forward<Ref>(ref)); } ||
              requires { c.insert(c.end(), std::forward<Ref>(ref)); });
  };
\end{codeblock}

\pnum
Let \exposid{container-append} be defined as follows:
\begin{codeblock}
template<class Container>
constexpr auto @\exposid{container-append}@(Container& c) {                    // \expos
  return [&c]<class Ref>(Ref&& ref) {
    if constexpr (requires { c.emplace_back(declval<Ref>()); })
      c.emplace_back(std::forward<Ref>(ref));
    else if constexpr (requires { c.push_back(declval<Ref>()); })
      c.push_back(std::forward<Ref>(ref));
    else if constexpr (requires { c.emplace(c.end(), declval<Ref>()); })
      c.emplace(c.end(), std::forward<Ref>(ref));
    else
      c.insert(c.end(), std::forward<Ref>(ref));
  };
}
\end{codeblock}

\rSec3[range.utility.conv.to]{\tcode{ranges::to}}

\indexlibrarymember{to}{ranges}%
\begin{itemdecl}
template<class C, @\libconcept{input_range}@ R, class... Args> requires (!@\libconcept{view}@<C>)
  constexpr C to(R&& r, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{C} is a cv-unqualified class type.

\pnum
\returns
An object of type \tcode{C}
constructed from the elements of \tcode{r} in the following manner:
\begin{itemize}
\item
If \tcode{C} does not satisfy \libconcept{input_range} or
\tcode{\libconcept{convertible_to}<range_reference_t<R>, range_value_t<C>>}
is \tcode{true}:
\begin{itemize}
\item
If \tcode{\libconcept{constructible_from}<C, R, Args...>} is \tcode{true}:
\begin{codeblock}
C(std::forward<R>(r), std::forward<Args>(args)...)
\end{codeblock}
\item
Otherwise, if
\tcode{\libconcept{constructible_from}<C, from_range_t, R, Args...>}
is \tcode{true}:
\begin{codeblock}
C(from_range, std::forward<R>(r), std::forward<Args>(args)...)
\end{codeblock}
\item
Otherwise, if
\begin{itemize}
\item
\tcode{\libconcept{common_range}<R>} is \tcode{true},
\item
the \grammarterm{qualified-id}
\tcode{iterator_traits<iterator_t<R>>::iterator_category}
is valid and denotes a type that models
\tcode{\libconcept{derived_from}<input_iterator_tag>}, and
\item
\tcode{\libconcept{constructible_from}<C, iterator_t<R>, sentinel_t<R>, Args...>}
is \tcode{true}:
\end{itemize}
\begin{codeblock}
C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)
\end{codeblock}
\item
Otherwise, if
\begin{itemize}
\item
\tcode{\libconcept{constructible_from}<C, Args...>} is \tcode{true}, and
\item
\tcode{\exposid{container-appendable}<C, range_reference_t<R>>} is \tcode{true}:
\end{itemize}
\begin{codeblock}
C c(std::forward<Args>(args)...);
if constexpr (@\libconcept{approximately_sized_range}@<R> && @\exposid{reservable-container}@<C>)
  c.reserve(static_cast<range_size_t<C>>(ranges::reserve_hint(r)));
ranges::for_each(r, @\exposid{container-append}@(c));
\end{codeblock}
\item
Otherwise, the program is ill-formed.
\end{itemize}

\item
Otherwise,
if \tcode{\libconcept{input_range}<range_reference_t<R>>} is \tcode{true}:
\begin{codeblock}
to<C>(ref_view(r) | views::transform([](auto&& elem) {
  return to<range_value_t<C>>(std::forward<decltype(elem)>(elem));
}), std::forward<Args>(args)...);
\end{codeblock}

\item
Otherwise, the program is ill-formed.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{to}{ranges}%
\begin{itemdecl}
template<template<class...> class C, @\libconcept{input_range}@ R, class... Args>
  constexpr auto to(R&& r, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \exposid{input-iterator} be an exposition-only type:
\begin{codeblock}
struct @\exposid{input-iterator}@ {                        // \expos
  using iterator_category = input_iterator_tag;
  using value_type = range_value_t<R>;
  using difference_type = ptrdiff_t;
  using pointer = add_pointer_t<range_reference_t<R>>;
  using reference = range_reference_t<R>;
  reference operator*() const;
  pointer operator->() const;
  @\exposid{input-iterator}@& operator++();
  @\exposid{input-iterator}@ operator++(int);
  bool operator==(const @\exposid{input-iterator}@&) const;
};
\end{codeblock}
\begin{note}
\exposid{input-iterator} meets
the syntactic requirements of \oldconcept{InputIterator}.
\end{note}

\pnum
Let \tcode{\placeholder{DEDUCE_EXPR}} be defined as follows:
\begin{itemize}
\item
\tcode{C(declval<R>(), declval<Args>()...)} if that is a valid expression,
\item
otherwise, \tcode{C(from_range, declval<R>(), declval<Args>()...)}
if that is a valid expression,
\item
otherwise,
\begin{codeblock}
C(declval<@\exposid{input-iterator}@>(), declval<@\exposid{input-iterator}@>(), declval<Args>()...)
\end{codeblock}
if that is a valid expression,
\item
otherwise, the program is ill-formed.
\end{itemize}

\pnum
\returns
\tcode{to<decltype(\placeholder{DEDUCE_EXPR})>(std::forward<R>(r), std::forward<Args>(args)...)}.
\end{itemdescr}

\rSec3[range.utility.conv.adaptors]{\tcode{ranges::to} adaptors}

\indexlibrarymember{to}{ranges}%
\begin{itemdecl}
template<class C, class... Args> requires (!@\libconcept{view}@<C>)
  constexpr auto to(Args&&... args);
template<template<class...> class C, class... Args>
  constexpr auto to(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
For the first overload,
\tcode{C} is a cv-unqualified class type.

\pnum
\returns
A range adaptor closure object\iref{range.adaptor.object} \tcode{f}
that is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper}
with the following properties:
\begin{itemize}
\item
It has no target object.
\item
Its bound argument entities \tcode{bound_args} consist of
objects of types \tcode{decay_t<Args>...}
direct-non-list-initialized with \tcode{std::forward<Args>(args)...},
respectively.
\item
Its call pattern is \tcode{to<C>(r, bound_args...)},
where \tcode{r} is the argument used in a function call expression of \tcode{f}.
\end{itemize}
\end{itemdescr}

\rSec1[range.factories]{Range factories}

\rSec2[range.factories.general]{General}

\pnum
Subclause \ref{range.factories} defines \term{range factories},
which are utilities to create a view.

\pnum
Range factories are declared in namespace \tcode{std::ranges::views}.

\rSec2[range.empty]{Empty view}

\rSec3[range.empty.overview]{Overview}

\pnum
\tcode{empty_view} produces a view of no elements of
a particular type.

\pnum
\begin{example}
\begin{codeblock}
auto e = views::empty<int>;
static_assert(ranges::empty(e));
static_assert(0 == e.size());
\end{codeblock}
\end{example}

\rSec3[range.empty.view]{Class template \tcode{empty_view}}

\indexlibraryglobal{empty_view}%
\begin{codeblock}
namespace std::ranges {
  template<class T>
    requires is_object_v<T>
  class empty_view : public view_interface<empty_view<T>> {
  public:
    static constexpr T* begin() noexcept { return nullptr; }
    static constexpr T* end() noexcept { return nullptr; }
    static constexpr T* data() noexcept { return nullptr; }
    static constexpr size_t size() noexcept { return 0; }
    static constexpr bool empty() noexcept { return true; }
  };
}
\end{codeblock}

\rSec2[range.single]{Single view}

\rSec3[range.single.overview]{Overview}

\pnum
\tcode{single_view} produces a view that contains
exactly one element of a specified value.

\pnum
\indexlibrarymember{single}{views}%
The name \tcode{views::single} denotes a
customization point object\iref{customization.point.object}.
Given a subexpression \tcode{E}, the expression
\tcode{views::single(E)} is expression-equivalent to
\tcode{single_view<decay_t<decltype((E))>>(E)}.

\pnum
\begin{example}
\begin{codeblock}
for (int i : views::single(4))
  cout << i;        // prints \tcode{4}
\end{codeblock}
\end{example}

\rSec3[range.single.view]{Class template \tcode{single_view}}

\indexlibraryglobal{single_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{move_constructible}@ T>
    requires is_object_v<T>
  class single_view : public view_interface<single_view<T>> {
  private:
    @\exposidnc{movable-box}@<T> @\exposidnc{value_}@;              // \expos{} (see \ref{range.move.wrap})

  public:
    single_view() requires @\libconcept{default_initializable}@<T> = default;
    constexpr explicit single_view(const T& t) requires @\libconcept{copy_constructible}@<T>;
    constexpr explicit single_view(T&& t);
    template<class... Args>
      requires @\libconcept{constructible_from}@<T, Args...>
    constexpr explicit single_view(in_place_t, Args&&... args);

    constexpr T* begin() noexcept;
    constexpr const T* begin() const noexcept;
    constexpr T* end() noexcept;
    constexpr const T* end() const noexcept;
    static constexpr bool empty() noexcept;
    static constexpr size_t size() noexcept;
    constexpr T* data() noexcept;
    constexpr const T* data() const noexcept;
  };

  template<class T>
    single_view(T) -> single_view<T>;
}
\end{codeblock}

\indexlibraryctor{single_view}%
\begin{itemdecl}
constexpr explicit single_view(const T& t) requires @\libconcept{copy_constructible}@<T>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{value_} with \tcode{t}.
\end{itemdescr}

\indexlibraryctor{single_view}%
\begin{itemdecl}
constexpr explicit single_view(T&& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{value_} with \tcode{std::move(t)}.
\end{itemdescr}

\indexlibraryctor{single_view}%
\begin{itemdecl}
template<class... Args>
  requires @\libconcept{constructible_from}@<T, Args...>
constexpr explicit single_view(in_place_t, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{value_} as if by
\tcode{\exposid{value_}\{in_place, std::forward<Args>(args)...\}}.
\end{itemdescr}

\indexlibrarymember{begin}{single_view}%
\begin{itemdecl}
constexpr T* begin() noexcept;
constexpr const T* begin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return data();}
\end{itemdescr}

\indexlibrarymember{end}{single_view}%
\begin{itemdecl}
constexpr T* end() noexcept;
constexpr const T* end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return data() + 1;}
\end{itemdescr}

\indexlibrarymember{empty}{single_view}%
\begin{itemdecl}
static constexpr bool empty() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return false;}
\end{itemdescr}

\indexlibrarymember{size}{single_view}%
\begin{itemdecl}
static constexpr size_t size() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return 1;}
\end{itemdescr}

\indexlibrarymember{data}{single_view}%
\begin{itemdecl}
constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{value_}.operator->();}
\end{itemdescr}

\rSec2[range.iota]{Iota view}

\rSec3[range.iota.overview]{Overview}

\pnum
\tcode{iota_view} generates a
sequence of elements by repeatedly incrementing an initial value.

\pnum
\indexlibrarymember{iota}{views}%
The name \tcode{views::iota} denotes a
customization point object\iref{customization.point.object}.
Given subexpressions \tcode{E} and \tcode{F}, the expressions
\tcode{views::iota(E)} and \tcode{views::iota(E, F)}
are expression-equivalent to
\tcode{iota_view<decay_t<decltype((E))>>(E)} and \tcode{iota_view(E, F)},
respectively.

\pnum
\begin{example}
\begin{codeblock}
for (int i : views::iota(1, 10))
  cout << i << ' '; // prints \tcode{1 2 3 4 5 6 7 8 9}
\end{codeblock}
\end{example}

\pnum
\indexlibrarymember{indices}{views}%
The name \tcode{views::indices} denotes a
customization point object\iref{customization.point.object}.
Given subexpression \tcode{E},
let \tcode{T} be \tcode{remove_cvref_t<decltype((E))>}.
\tcode{views::indices(E)} is expression-equivalent to
\tcode{views::iota(T(0), E)}
if \tcode{\exposid{is-integer-like}<T>} is \tcode{true},
and ill-formed otherwise.

\rSec3[range.iota.view]{Class template \tcode{iota_view}}

\indexlibraryglobal{iota_view}%
\begin{codeblock}
namespace std::ranges {
  template<class I>
    concept @\exposconceptnc{decrementable}@ = @\seebelownc@;  // \expos

  template<class I>
    concept @\exposconceptnc{advanceable}@ = @\seebelownc@;    // \expos

  template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t>
    requires @\exposconcept{weakly-equality-comparable-with}@<W, Bound> && @\libconcept{copyable}@<W>
  class iota_view : public view_interface<iota_view<W, Bound>> {
  private:
    // \ref{range.iota.iterator}, class \tcode{iota_view::\exposid{iterator}}
    struct @\exposidnc{iterator}@;                    // \expos

    // \ref{range.iota.sentinel}, class \tcode{iota_view::\exposid{sentinel}}
    struct @\exposidnc{sentinel}@;                    // \expos

    W @\exposid{value_}@ = W();                     // \expos
    Bound @\exposid{bound_}@ = Bound();             // \expos

  public:
    iota_view() requires @\libconcept{default_initializable}@<W> = default;
    constexpr explicit iota_view(W value);
    constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
    constexpr explicit iota_view(@\exposid{iterator}@ first, @\seebelow@ last);

    constexpr @\exposid{iterator}@ begin() const;
    constexpr auto end() const;
    constexpr @\exposid{iterator}@ end() const requires @\libconcept{same_as}@<W, Bound>;

    constexpr bool empty() const;
    constexpr auto size() const requires @\seebelow@;
  };

  template<class W, class Bound>
    requires (!@\exposid{is-integer-like}@<W> || !@\exposid{is-integer-like}@<Bound> ||
              (@\exposid{is-signed-integer-like}@<W> == @\exposid{is-signed-integer-like}@<Bound>))
    iota_view(W, Bound) -> iota_view<W, Bound>;
}
\end{codeblock}

\pnum
Let \tcode{\placeholdernc{IOTA-DIFF-T}(W)} be defined as follows:
\begin{itemize}
\item
  If \tcode{W} is not an integral type, or
  if it is an integral type and \tcode{sizeof(iter_difference_t<W>)}
  is greater than \tcode{sizeof(W)},
  then \tcode{\placeholdernc{IOTA-DIFF-T}(W)} denotes \tcode{iter_difference_t<W>}.
\item
  Otherwise, \tcode{\placeholdernc{IOTA-DIFF-T}(W)}
  is a signed integer type of width greater than the width of \tcode{W}
  if such a type exists.
\item
  Otherwise, \tcode{\placeholdernc{IOTA-DIFF-T}(W)}
  is an unspecified signed-integer-like type\iref{iterator.concept.winc}
  of width not less than the width of \tcode{W}.
  \begin{note}
  It is unspecified
  whether this type satisfies \libconcept{weakly_incrementable}.
  \end{note}
\end{itemize}

\pnum
The exposition-only \defexposconcept{decrementable} concept is equivalent to:
\begin{itemdecl}
template<class I>
  concept @\defexposconcept{decrementable}@ =               // \expos
    @\libconcept{incrementable}@<I> && requires(I i) {
      { --i } -> @\libconcept{same_as}@<I&>;
      { i-- } -> @\libconcept{same_as}@<I>;
    };
\end{itemdecl}

\begin{itemdescr}
\pnum
When an object is in the domain of both pre- and post-decrement,
the object is said to be \term{decrementable}.

\pnum
Let \tcode{a} and \tcode{b} be equal objects of type \tcode{I}.
\tcode{I} models \exposconcept{decrementable} only if
\begin{itemize}
\item If \tcode{a} and \tcode{b} are decrementable,
  then the following are all true:
  \begin{itemize}
  \item \tcode{addressof(--a) == addressof(a)}
  \item \tcode{bool(a-- == b)}
  \item \tcode{bool(((void)a--, a) == --b)}
  \item \tcode{bool(++(--a) == b)}.
  \end{itemize}
\item If \tcode{a} and \tcode{b} are incrementable,
  then \tcode{bool(--(++a) == b)}.
\end{itemize}
\end{itemdescr}

\pnum
The exposition-only \defexposconcept{advanceable} concept is equivalent to:
\begin{itemdecl}
template<class I>
  concept @\defexposconcept{advanceable}@ =                 // \expos
    @\exposconcept{decrementable}@<I> && @\libconcept{totally_ordered}@<I> &&
    requires(I i, const I j, const @\placeholdernc{IOTA-DIFF-T}@(I) n) {
      { i += n } -> @\libconcept{same_as}@<I&>;
      { i -= n } -> @\libconcept{same_as}@<I&>;
      I(j + n);
      I(n + j);
      I(j - n);
      { j - j } -> @\libconcept{convertible_to}@<@\placeholdernc{IOTA-DIFF-T}@(I)>;
    };
\end{itemdecl}

Let \tcode{D} be \tcode{\placeholdernc{IOTA-DIFF-T}(I)}.
Let \tcode{a} and \tcode{b} be objects of type \tcode{I} such that
\tcode{b} is reachable from \tcode{a}
after \tcode{n} applications of \tcode{++a},
for some value \tcode{n} of type \tcode{D}.
\tcode{I} models \exposconcept{advanceable} only if
\begin{itemize}
\item \tcode{(a += n)} is equal to \tcode{b}.
\item \tcode{addressof(a += n)} is equal to \tcode{addressof(a)}.
\item \tcode{I(a + n)} is equal to \tcode{(a += n)}.
\item For any two positive values
  \tcode{x} and \tcode{y} of type \tcode{D},
  if \tcode{I(a + D(x + y))} is well-defined, then
  \tcode{I(a + D(x + y))} is equal to \tcode{I(I(a + x) + y)}.
\item \tcode{I(a + D(0))} is equal to \tcode{a}.
\item If \tcode{I(a + D(n - 1))} is well-defined, then
  \tcode{I(a + n)} is equal to \tcode{[](I c) \{ return ++c; \}(I(a + D(n - 1)))}.
\item \tcode{(b += -n)} is equal to \tcode{a}.
\item \tcode{(b -= n)} is equal to \tcode{a}.
\item \tcode{addressof(b -= n)} is equal to \tcode{addressof(b)}.
\item \tcode{I(b - n)} is equal to \tcode{(b -= n)}.
\item \tcode{D(b - a)} is equal to \tcode{n}.
\item \tcode{D(a - b)} is equal to \tcode{D(-n)}.
\item \tcode{bool(a <= b)} is \tcode{true}.
\end{itemize}

\indexlibraryctor{iota_view}%
\begin{itemdecl}
constexpr explicit iota_view(W value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{Bound} denotes \tcode{unreachable_sentinel_t} or
\tcode{Bound()} is reachable from \tcode{value}.
When \tcode{W} and \tcode{Bound} model \libconcept{totally_ordered_with},
then \tcode{bool(value <= Bound())} is \tcode{true}.

\pnum
\effects
Initializes \exposid{value_} with \tcode{value}.
\end{itemdescr}

\indexlibraryctor{iota_view}%
\begin{itemdecl}
constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{Bound} denotes \tcode{unreachable_sentinel_t} or
\tcode{bound} is reachable from \tcode{value}.
When \tcode{W} and \tcode{Bound} model \libconcept{totally_ordered_with},
then \tcode{bool(value <= bound)} is \tcode{true}.

\pnum
\effects
Initializes \exposid{value_} with \tcode{value} and
\exposid{bound_} with \tcode{bound}.
\end{itemdescr}

\indexlibraryctor{iota_view}%
\begin{itemdecl}
constexpr explicit iota_view(@\exposid{iterator}@ first, @\seebelow@ last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{itemize}
\item
If \tcode{\libconcept{same_as}<W, Bound>} is \tcode{true},
\tcode{iota_view(first.\exposid{value_}, last.\exposid{value_})}.
\item
Otherwise, if \tcode{Bound} denotes \tcode{unreachable_sentinel_t},
\tcode{iota_view(first.\exposid{value_}, last)}.
\item
Otherwise, \tcode{iota_view(first.\exposid{value_}, last.\exposid{bound_})}.
\end{itemize}

\pnum
\remarks
The type of \tcode{last} is:
\begin{itemize}
\item
If \tcode{\libconcept{same_as}<W, Bound>} is \tcode{true}, \exposid{iterator}.
\item
Otherwise, if \tcode{Bound} denotes \tcode{unreachable_sentinel_t},
\tcode{Bound}.
\item
Otherwise, \exposid{sentinel}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{begin}{iota_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ begin() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}\{\exposid{value_}\};}
\end{itemdescr}

\indexlibrarymember{end}{iota_view}%
\begin{itemdecl}
constexpr auto end() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\libconcept{same_as}@<Bound, unreachable_sentinel_t>)
  return unreachable_sentinel;
else
  return @\exposid{sentinel}@{@\exposid{bound_}@};
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{iota_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ end() const requires @\libconcept{same_as}@<W, Bound>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}\{\exposid{bound_}\};}
\end{itemdescr}

\indexlibrarymember{empty}{iota_view}%
\begin{itemdecl}
constexpr bool empty() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{value_} == \exposid{bound_};}
\end{itemdescr}

\indexlibrarymember{size}{iota_view}%
\begin{itemdecl}
constexpr auto size() const requires @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\exposid{is-integer-like}@<W> && @\exposid{is-integer-like}@<Bound>)
  return (@\exposid{value_}@ < 0)
    ? ((@\exposid{bound_}@ < 0)
      ? @\placeholdernc{to-unsigned-like}@(-@\exposid{value_}@) - @\placeholdernc{to-unsigned-like}@(-@\exposid{bound_}@)
      : @\placeholdernc{to-unsigned-like}@(@\exposid{bound_}@) + @\placeholdernc{to-unsigned-like}@(-@\exposid{value_}@))
    : @\placeholdernc{to-unsigned-like}@(@\exposid{bound_}@) - @\placeholdernc{to-unsigned-like}@(@\exposid{value_}@);
else
  return @\placeholdernc{to-unsigned-like}@(@\exposid{bound_}@ - @\exposid{value_}@);
\end{codeblock}

\pnum
\remarks
The expression in the \grammarterm{requires-clause} is equivalent to:
\begin{codeblock}
(@\libconcept{same_as}@<W, Bound> && @\exposconcept{advanceable}@<W>) || (@\exposid{is-integer-like}@<W> && @\exposid{is-integer-like}@<Bound>) ||
  @\libconcept{sized_sentinel_for}@<Bound, W>
\end{codeblock}
\end{itemdescr}

\rSec3[range.iota.iterator]{Class \tcode{iota_view::\exposid{iterator}}}

\indexlibraryglobal{iota_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound>
    requires @\exposconcept{weakly-equality-comparable-with}@<W, Bound> && @\libconcept{copyable}@<W>
  struct iota_view<W, Bound>::@\exposid{iterator}@ {
  private:
    W @\exposid{value_}@ = W();                             // \expos
    constexpr explicit @\exposid{iterator}@(W value);       // \expos

  public:
    using iterator_concept = @\seebelow@;
    using iterator_category = input_iterator_tag;       // present only if \tcode{W} models \libconcept{incrementable} and
                                                        // \tcode{\placeholdernc{IOTA-DIFF-T}(W)} is an integral type
    using value_type = W;
    using difference_type = @\placeholdernc{IOTA-DIFF-T}@(W);

    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<W> = default;

    constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{incrementable}@<W>;

    constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{decrementable}@<W>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{decrementable}@<W>;

    constexpr @\exposid{iterator}@& operator+=(difference_type n)
      requires @\exposconcept{advanceable}@<W>;
    constexpr @\exposid{iterator}@& operator-=(difference_type n)
      requires @\exposconcept{advanceable}@<W>;
    constexpr W operator[](difference_type n) const
      requires @\exposconcept{advanceable}@<W>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<W>;

    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{totally_ordered}@<W>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{totally_ordered}@<W>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{totally_ordered}@<W>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{totally_ordered}@<W>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{totally_ordered}@<W> && @\libconcept{three_way_comparable}@<W>;

    friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n)
      requires @\exposconcept{advanceable}@<W>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i)
      requires @\exposconcept{advanceable}@<W>;

    friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n)
      requires @\exposconcept{advanceable}@<W>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{advanceable}@<W>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item If \tcode{W} models \exposconcept{advanceable}, then
\tcode{iterator_concept} is \tcode{random_access_iterator_tag}.
\item Otherwise, if \tcode{W} models \exposconcept{decrementable}, then
\tcode{iterator_concept} is \tcode{bidirectional_iterator_tag}.
\item Otherwise, if \tcode{W} models \libconcept{incrementable}, then
\tcode{iterator_concept} is \tcode{forward_iterator_tag}.
\item Otherwise, \tcode{iterator_concept} is \tcode{input_iterator_tag}.
\end{itemize}

\pnum
\begin{note}
Overloads for \tcode{iter_move} and \tcode{iter_swap} are omitted intentionally.
\end{note}

\indexlibraryctor{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(W value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{value_} with \tcode{value}.
\end{itemdescr}

\indexlibrarymember{operator*}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{value_};}

\pnum
\begin{note}
The \keyword{noexcept} clause is needed by the default \tcode{iter_move}
implementation.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator++}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{value_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{incrementable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{decrementable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{value_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{decrementable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n)
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\exposid{is-integer-like}@<W> && !@\exposid{is-signed-integer-like}@<W>) {
  if (n >= difference_type(0))
    @\exposid{value_}@ += static_cast<W>(n);
  else
    @\exposid{value_}@ -= static_cast<W>(-n);
} else {
  @\exposid{value_}@ += n;
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type n)
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\exposid{is-integer-like}@<W> && !@\exposid{is-signed-integer-like}@<W>) {
  if (n >= difference_type(0))
    @\exposid{value_}@ -= static_cast<W>(n);
  else
    @\exposid{value_}@ += static_cast<W>(-n);
} else {
  @\exposid{value_}@ -= n;
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{iota_view::\exposid{iterator}}
\begin{itemdecl}
constexpr W operator[](difference_type n) const
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return W(\exposid{value_} + n);}
\end{itemdescr}

\indexlibrarymember{operator==}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{value_} == y.\exposid{value_};}
\end{itemdescr}

\indexlibrarymember{operator<}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{totally_ordered}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{value_} < y.\exposid{value_};}
\end{itemdescr}

\indexlibrarymember{operator>}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{totally_ordered}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{totally_ordered}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{totally_ordered}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{totally_ordered}@<W> && @\libconcept{three_way_comparable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{value_} <=> y.\exposid{value_};}
\end{itemdescr}

\indexlibrarymember{operator+}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n)
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
i += n;
return i;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i)
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return i + n;}
\end{itemdescr}

\indexlibrarymember{operator-}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n)
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
i -= n;
return i;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{iota_view::\exposid{iterator}}
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{advanceable}@<W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
using D = difference_type;
if constexpr (@\exposid{is-integer-like}@<W>) {
  if constexpr (@\exposid{is-signed-integer-like}@<W>)
    return D(D(x.@\exposid{value_}@) - D(y.@\exposid{value_}@));
  else
    return (y.@\exposid{value_}@ > x.@\exposid{value_}@)
      ? D(-D(y.@\exposid{value_}@ - x.@\exposid{value_}@))
      : D(x.@\exposid{value_}@ - y.@\exposid{value_}@);
} else {
  return x.@\exposid{value_}@ - y.@\exposid{value_}@;
}
\end{codeblock}
\end{itemdescr}

\rSec3[range.iota.sentinel]{Class \tcode{iota_view::\exposid{sentinel}}}

\indexlibraryglobal{iota_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound>
    requires @\exposconcept{weakly-equality-comparable-with}@<W, Bound> && @\libconcept{copyable}@<W>
  struct iota_view<W, Bound>::@\exposid{sentinel}@ {
  private:
    Bound @\exposid{bound_}@ = Bound();                     // \expos
    constexpr explicit @\exposid{sentinel}@(Bound bound);   // \expos

  public:
    @\exposid{sentinel}@() = default;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y);

    friend constexpr iter_difference_t<W> operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y)
      requires @\libconcept{sized_sentinel_for}@<Bound, W>;
    friend constexpr iter_difference_t<W> operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<Bound, W>;
  };
}
\end{codeblock}

\indexlibraryctor{iota_view::\exposid{sentinel}}
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(Bound bound);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{bound_} with \tcode{bound}.
\end{itemdescr}

\indexlibrarymember{operator==}{iota_view::\exposid{sentinel}}
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{value_} == y.\exposid{bound_};}
\end{itemdescr}

\indexlibrarymember{operator-}{iota_view::\exposid{sentinel}}
\begin{itemdecl}
friend constexpr iter_difference_t<W> operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y)
  requires @\libconcept{sized_sentinel_for}@<Bound, W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{value_} - y.\exposid{bound_};}
\end{itemdescr}

\indexlibrarymember{operator-}{iota_view::\exposid{sentinel}}
\begin{itemdecl}
friend constexpr iter_difference_t<W> operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<Bound, W>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(y - x);}
\end{itemdescr}

\rSec2[range.repeat]{Repeat view}

\rSec3[range.repeat.overview]{Overview}

\pnum
\tcode{repeat_view} generates a sequence of elements
by repeatedly producing the same value.

\pnum
\indexlibrarymember{repeat}{views}%
The name \tcode{views::repeat} denotes
a customization point object\iref{customization.point.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expressions \tcode{views::repeat(E)} and \tcode{views::repeat(E, F)}
are expression-equivalent to
\tcode{repeat_view<decay_t<decltype((E))>>(E)} and \tcode{repeat_view(E, F)}, respectively.

\pnum
\begin{example}
\begin{codeblock}
for (int i : views::repeat(17, 4))
  cout << i << ' ';
// prints \tcode{17 17 17 17}
\end{codeblock}
\end{example}

\rSec3[range.repeat.view]{Class template \tcode{repeat_view}}

\begin{codeblock}
namespace std::ranges {
  template<class T>
    concept @\defexposconceptnc{integer-like-with-usable-difference-type}@ =  // \expos
      @\exposid{is-signed-integer-like}@<T> || (@\exposid{is-integer-like}@<T> && @\libconcept{weakly_incrementable}@<T>);

  template<@\libconcept{move_constructible}@ T, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t>
    requires (is_object_v<T> && @\libconcept{same_as}@<T, remove_cv_t<T>> &&
              (@\exposconcept{integer-like-with-usable-difference-type}@<Bound> ||
               @\libconcept{same_as}@<Bound, unreachable_sentinel_t>))
  class @\libglobal{repeat_view}@ : public view_interface<repeat_view<T, Bound>> {
  private:
    // \ref{range.repeat.iterator}, class \tcode{repeat_view::\exposid{iterator}}
    struct @\exposidnc{iterator}@;                            // \expos

    @\exposidnc{movable-box}@<T> @\exposid{value_}@;                      // \expos, see \ref{range.move.wrap}
    Bound @\exposid{bound_}@ = Bound();                     // \expos

  public:
    repeat_view() requires @\libconcept{default_initializable}@<T> = default;

    constexpr explicit repeat_view(const T& value, Bound bound = Bound())
      requires @\libconcept{copy_constructible}@<T>;
    constexpr explicit repeat_view(T&& value, Bound bound = Bound());
    template<class... TArgs, class... BoundArgs>
      requires @\libconcept{constructible_from}@<T, TArgs...> &&
               @\libconcept{constructible_from}@<Bound, BoundArgs...>
    constexpr explicit repeat_view(piecewise_construct_t,
      tuple<TArgs...> value_args, tuple<BoundArgs...> bound_args = tuple<>{});

    constexpr @\exposid{iterator}@ begin() const;
    constexpr @\exposid{iterator}@ end() const requires (!@\libconcept{same_as}@<Bound, unreachable_sentinel_t>);
    constexpr unreachable_sentinel_t end() const noexcept;

    constexpr auto size() const requires (!@\libconcept{same_as}@<Bound, unreachable_sentinel_t>);
  };

  template<class T, class Bound = unreachable_sentinel_t>
    repeat_view(T, Bound = Bound()) -> repeat_view<T, Bound>;
}
\end{codeblock}

\indexlibraryctor{repeat_view}%
\begin{itemdecl}
constexpr explicit repeat_view(const T& value, Bound bound = Bound())
  requires @\libconcept{copy_constructible}@<T>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{Bound} is not \tcode{unreachable_sentinel_t},
$\tcode{bound} \ge 0$.

\pnum
\effects
Initializes \exposid{value_} with \tcode{value} and
\exposid{bound_} with \tcode{bound}.
\end{itemdescr}

\indexlibraryctor{repeat_view}%
\begin{itemdecl}
constexpr explicit repeat_view(T&& value, Bound bound = Bound());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{Bound} is not \tcode{unreachable_sentinel_t}, $\tcode{bound} \ge 0$.

\pnum
\effects
Initializes \exposid{value_} with \tcode{std::move(value)} and
\exposid{bound_} with \tcode{bound}.
\end{itemdescr}

\indexlibraryctor{repeat_view}%
\begin{itemdecl}
template<class... TArgs, class... BoundArgs>
  requires @\libconcept{constructible_from}@<T, TArgs...> &&
           @\libconcept{constructible_from}@<Bound, BoundArgs...>
constexpr explicit repeat_view(piecewise_construct_t,
  tuple<TArgs...> value_args, tuple<BoundArgs...> bound_args = tuple<>{});
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{value_} with
\tcode{make_from_tuple<T>(std::move(value_args))}
and
initializes\linebreak{} \exposid{bound_} with
\tcode{make_from_tuple<Bound>(std::move(bound_args))}.
The behavior is undefined if
\tcode{Bound} is not \tcode{unreachable_sentinel_t} and
\exposid{bound_} is negative.
\end{itemdescr}

\indexlibrarymember{begin}{repeat_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ begin() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(addressof(*\exposid{value_}));}
\end{itemdescr}

\indexlibrarymember{end}{repeat_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ end() const requires (!@\libconcept{same_as}@<Bound, unreachable_sentinel_t>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(addressof(*\exposid{value_}), \exposid{bound_});}
\end{itemdescr}

\indexlibrarymember{end}{repeat_view}%
\begin{itemdecl}
constexpr unreachable_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return unreachable_sentinel;}
\end{itemdescr}

\indexlibrarymember{size}{repeat_view}%
\begin{itemdecl}
constexpr auto size() const requires (!@\libconcept{same_as}@<Bound, unreachable_sentinel_t>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{to-unsigned-like}(\exposid{bound_});}
\end{itemdescr}

\rSec3[range.repeat.iterator]{Class \tcode{repeat_view::\exposid{iterator}}}

\indexlibraryglobal{repeat_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{move_constructible}@ T, @\libconcept{semiregular}@ Bound>
    requires (is_object_v<T> && @\libconcept{same_as}@<T, remove_cv_t<T>> &&
              (@\exposconcept{integer-like-with-usable-difference-type}@<Bound> ||
               @\libconcept{same_as}@<Bound, unreachable_sentinel_t>))
  class repeat_view<T, Bound>::@\exposid{iterator}@ {
  private:
    using @\exposidnc{index-type}@ =                          // \expos
      conditional_t<@\libconcept{same_as}@<Bound, unreachable_sentinel_t>, ptrdiff_t, Bound>;
    const T* @\exposidnc{value_}@ = nullptr;                  // \expos
    @\exposidnc{index-type}@ @\exposidnc{current_}@ = @\exposidnc{index-type}@();         // \expos

    constexpr explicit @\exposid{iterator}@(const T* value, @\exposid{index-type}@ b = @\exposidnc{index-type}@());   // \expos

  public:
    using iterator_concept = random_access_iterator_tag;
    using iterator_category = random_access_iterator_tag;
    using value_type = T;
    using difference_type = @\seebelow@;

    @\exposid{iterator}@() = default;

    constexpr const T& operator*() const noexcept;

    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);

    constexpr @\exposid{iterator}@& operator--();
    constexpr @\exposid{iterator}@ operator--(int);

    constexpr @\exposid{iterator}@& operator+=(difference_type n);
    constexpr @\exposid{iterator}@& operator-=(difference_type n);
    constexpr const T& operator[](difference_type n) const noexcept;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);

    friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n);
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i);

    friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n);
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
  };
}
\end{codeblock}

\pnum
If \tcode{\exposid{is-signed-integer-like}<\exposid{index-type}>} is \tcode{true},
the member \grammarterm{typedef-name} \tcode{difference_type}
denotes \exposid{index-type}.
Otherwise, it denotes \tcode{\placeholdernc{IOTA-DIFF-T}(\exposid{index-type})}\iref{range.iota.view}.

\indexlibraryctor{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(const T* value, @\exposid{index-type}@ b = @\exposid{index-type}@());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{Bound} is not \tcode{unreachable_sentinel_t}, $\tcode{b} \ge 0$.

\pnum
\effects
Initializes \exposid{value_} with \tcode{value} and
\exposid{current_} with \tcode{b}.
\end{itemdescr}

\indexlibrarymember{operator*}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const T& operator*() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{value_};}
\end{itemdescr}

\indexlibrarymember{operator++}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{Bound} is not \tcode{unreachable_sentinel_t},
$\exposid{current_} > 0$.

\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{Bound} is not \tcode{unreachable_sentinel_t},
$\exposid{current_} + \tcode{n} \ge 0$.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ += n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{Bound} is not \tcode{unreachable_sentinel_t},
$\exposid{current_} - \tcode{n} \ge 0$.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ -= n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const T& operator[](difference_type n) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *(*this + n);}
\end{itemdescr}

\indexlibrarymember{operator==}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator<=>}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator+}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n);
friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
i += n;
return i;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
i -= n;
return i;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{repeat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return static_cast<difference_type>(x.@\exposid{current_}@) - static_cast<difference_type>(y.@\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\rSec2[range.istream]{Istream view}

\rSec3[range.istream.overview]{Overview}

\pnum
\tcode{basic_istream_view} models \libconcept{input_range} and
reads (using \tcode{operator>>}) successive elements
from its corresponding input stream.

\pnum
The name \tcode{views::istream<T>} denotes
a customization point object\iref{customization.point.object}.
Given a type \tcode{T} and a subexpression \tcode{E} of type \tcode{U},
if \tcode{U} models
\tcode{\libconcept{derived_from}<basic_istream<typename U::char_type,
typename U::traits_type>>},
then the expression \tcode{views::istream<T>(E)} is expression-equivalent to
\tcode{basic_istream_view<T, typename U::char_type,
typename U::traits_type>(E)};
otherwise, \tcode{views::istream<T>(E)} is ill-formed.

\pnum
\begin{example}
\begin{codeblock}
auto ints = istringstream{"0 1  2   3     4"};
ranges::copy(views::istream<int>(ints), ostream_iterator<int>{cout, "-"});
// prints \tcode{0-1-2-3-4-}
\end{codeblock}
\end{example}

\rSec3[range.istream.view]{Class template \tcode{basic_istream_view}}

\indexlibraryglobal{basic_istream_view}%
\begin{codeblock}
namespace std::ranges {
  template<class Val, class CharT, class Traits>
    concept @\defexposconceptnc{stream-extractable}@ =                // \expos
      requires(basic_istream<CharT, Traits>& is, Val& t) {
        is >> t;
      };

  template<@\libconcept{movable}@ Val, class CharT, class Traits = char_traits<CharT>>
    requires @\libconcept{default_initializable}@<Val> &&
             @\exposconcept{stream-extractable}@<Val, CharT, Traits>
  class basic_istream_view : public view_interface<basic_istream_view<Val, CharT, Traits>> {
  public:
    constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);

    constexpr auto begin() {
      *@\exposid{stream_}@ >> @\exposid{value_}@;
      return @\exposid{iterator}@{*this};
    }

    constexpr default_sentinel_t end() const noexcept;

  private:
    // \ref{range.istream.iterator}, class \tcode{basic_istream_view::\exposid{iterator}}
    struct @\exposidnc{iterator}@;                            // \expos
    basic_istream<CharT, Traits>* @\exposid{stream_}@;      // \expos
    Val @\exposid{value_}@ = Val();                         // \expos
  };
}
\end{codeblock}

\indexlibraryctor{basic_istream_view}%
\begin{itemdecl}
constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{stream_} with \tcode{addressof(stream)}.
\end{itemdescr}

\indexlibrarymember{end}{basic_istream_view}%
\begin{itemdecl}
constexpr default_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return default_sentinel;}
\end{itemdescr}

\rSec3[range.istream.iterator]{Class \tcode{basic_istream_view::\exposid{iterator}}}

\indexlibraryglobal{basic_istream_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{movable}@ Val, class CharT, class Traits>
    requires @\libconcept{default_initializable}@<Val> &&
             @\exposconcept{stream-extractable}@<Val, CharT, Traits>
  class basic_istream_view<Val, CharT, Traits>::@\exposid{iterator}@ {
  public:
    using iterator_concept = input_iterator_tag;
    using difference_type = ptrdiff_t;
    using value_type = Val;

    @\exposid{iterator}@(const @\exposid{iterator}@&) = delete;
    @\exposid{iterator}@(@\exposid{iterator}@&&) = default;

    @\exposid{iterator}@& operator=(const @\exposid{iterator}@&) = delete;
    @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default;

    @\exposid{iterator}@& operator++();
    void operator++(int);

    Val& operator*() const;

    friend bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);

  private:
    constexpr explicit @\exposid{iterator}@(basic_istream_view& parent) noexcept;   // \expos
    basic_istream_view* @\exposid{parent_}@;                                        // \expos
  };
}
\end{codeblock}

\indexlibraryctor{basic_istream_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(basic_istream_view& parent) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibrarymember{operator++}{basic_istream_view::\exposid{iterator}}%
\begin{itemdecl}
@\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
*@\exposid{parent_}@->@\exposid{stream_}@ >> @\exposid{parent_}@->@\exposid{value_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{basic_istream_view::\exposid{iterator}}%
\begin{itemdecl}
void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator*}{basic_istream_view::\exposid{iterator}}%
\begin{itemdecl}
Val& operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{parent_}->\exposid{value_};}
\end{itemdescr}

\indexlibrarymember{operator==}{basic_istream_view::\exposid{iterator}}%
\begin{itemdecl}
friend bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !*x.\exposid{parent_}->\exposid{stream_};}
\end{itemdescr}

\rSec1[range.adaptors]{Range adaptors}

\rSec2[range.adaptors.general]{General}

\pnum
Subclause \ref{range.adaptors} defines \term{range adaptors}, which are utilities that transform a
range into a view with custom behaviors. These
adaptors can be chained to create pipelines of range transformations that
evaluate lazily as the resulting view is iterated.

\pnum
Range adaptors are declared in namespace \tcode{std::ranges::views}.

\pnum
The bitwise \logop{or} operator is overloaded for the purpose of creating adaptor chain
pipelines. The adaptors also support function call syntax with equivalent
semantics.

\pnum
\begin{example}
\begin{codeblock}
vector<int> ints{0,1,2,3,4,5};
auto even = [](int i) { return 0 == i % 2; };
auto square = [](int i) { return i * i; };
for (int i : ints | views::filter(even) | views::transform(square)) {
  cout << i << ' '; // prints \tcode{0 4 16}
}
assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
\end{codeblock}
\end{example}

\rSec2[range.adaptor.object]{Range adaptor objects}

\indexlibrarymisc{\idxcode{operator"|}}{range adaptor closure objects}%
\pnum
A \defnadj{range adaptor closure}{object} is a unary function object that accepts
a range argument. For
a range adaptor closure object \tcode{C} and an expression \tcode{R} such that
\tcode{decltype((R))} models \libconcept{range}, the following
expressions are equivalent:
\begin{codeblock}
C(R)
R | C
\end{codeblock}
Given an additional range adaptor closure object \tcode{D},
the expression \tcode{C | D} produces another range adaptor
closure object \tcode{E}.
\tcode{E} is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper}
with the following properties:
\begin{itemize}
\item
Its target object is an object \tcode{d} of type \tcode{decay_t<decltype((D))>}
direct-non-list-initialized with \tcode{D}.
\item
It has one bound argument entity,
an object \tcode{c} of type \tcode{decay_t<decltype((C))>}
direct-non-list-initialized with \tcode{C}.
\item
Its call pattern is \tcode{d(c(arg))},
where \tcode{arg} is the argument used in
a function call expression of \tcode{E}.
\end{itemize}
The expression \tcode{C | D} is well-formed if and only if
the initializations of the state entities of \tcode{E} are all well-formed.

\pnum
Given an object \tcode{t} of type \tcode{T}, where
\begin{itemize}
\item
\tcode{t} is a unary function object that accepts a range argument,
\item
\tcode{T} models \tcode{\libconcept{derived_from}<range_adaptor_closure<T>>},
\item
\tcode{T} has no other base classes of type \tcode{range_adaptor_closure<U>} for any other type \tcode{U}, and
\item
\tcode{T} does not model \libconcept{range}
\end{itemize}
then the implementation ensures
that \tcode{t} is a range adaptor closure object.

\pnum
The template parameter \tcode{D} for \tcode{range_adaptor_closure}
may be an incomplete type.
If an expression of type \cv{} \tcode{D}
is used as an operand to the \tcode{|} operator,
\tcode{D} shall be complete and
model \tcode{\libconcept{derived_from}<range_adaptor_closure<D>>}.
The behavior of an expression involving an object of type \cv{} \tcode{D}
as an operand to the \tcode{|} operator is undefined
if overload resolution selects a program-defined \tcode{operator|} function.

\pnum
If an expression of type \cv{} \tcode{U}
is used as an operand to the \tcode{|} operator,
where \tcode{U} has a base class of type \tcode{range_adaptor_closure<T>}
for some type \tcode{T} other than \tcode{U}, the behavior is undefined.

\pnum
The behavior of a program
that adds a specialization for \tcode{range_adaptor_closure} is undefined.

\pnum
A \defnadj{range adaptor}{object} is a
customization point object\iref{customization.point.object}
that accepts a \libconcept{viewable_range} as its first argument and returns a view.

\pnum
If a range adaptor object accepts only one argument,
then it is a range adaptor closure object.

\pnum
If a range adaptor object \tcode{adaptor} accepts more than one argument,
then let \tcode{range} be an expression
such that \tcode{decltype((range))} models \libconcept{viewable_range},
let \tcode{args...} be arguments
such that \tcode{adaptor(range, args...)} is a well-formed expression
as specified in the rest of subclause~\ref{range.adaptors}, and
let \tcode{BoundArgs} be a pack
that denotes \tcode{decay_t<decltype((args))>...}.
The expression \tcode{adaptor(args...)} produces a range adaptor closure object \tcode{f}
that is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} with the following properties:
\begin{itemize}
\item
Its target object is a copy of \tcode{adaptor}.
\item
Its bound argument entities \tcode{bound_args} consist of objects of types \tcode{BoundArgs...} direct-non-list-initialized with \tcode{std::forward<decltype((args))>(args)...}, respectively.
\item
Its call pattern is \tcode{adaptor(r, bound_args...)},
where \tcode{r} is the argument used in a function call expression of \tcode{f}.
\end{itemize}
The expression \tcode{adaptor(args...)} is well-formed if and only if
the initialization of the bound argument entities of the result,
as specified above, are all well-formed.

\rSec2[range.move.wrap]{Movable wrapper}

\pnum
Many types in this subclause are specified in terms of
an exposition-only class template \exposid{movable-box}.
\tcode{\exposid{movable-box}<T>} behaves exactly like \tcode{optional<T>}
with the following differences:
\begin{itemize}
\item \tcode{\exposid{movable-box}<T>} constrains
its type parameter \tcode{T} with
\tcode{\libconcept{move_constructible}<T> \&\& is_object_v<T>}.

\item The default
constructor of \tcode{\exposid{movable-box}<T>} is equivalent to:
\begin{codeblock}
constexpr @\exposid{movable-box}@() noexcept(is_nothrow_default_constructible_v<T>)
    requires @\libconcept{default_initializable}@<T>
  : @\exposid{movable-box}@{in_place} {}
\end{codeblock}

\item If \tcode{\libconcept{copyable}<T>} is not
modeled, the copy assignment operator is equivalent to:
\begin{codeblock}
constexpr @\exposid{movable-box}@& operator=(const @\exposid{movable-box}@& that)
  noexcept(is_nothrow_copy_constructible_v<T>)
  requires @\libconcept{copy_constructible}@<T> {
  if (this != addressof(that)) {
    if (that) emplace(*that);
    else reset();
  }
  return *this;
}
\end{codeblock}

\item If \tcode{\libconcept{movable}<T>} is not modeled,
the move assignment operator is equivalent to:
\begin{codeblock}
constexpr @\exposid{movable-box}@& operator=(@\exposid{movable-box}@&& that)
  noexcept(is_nothrow_move_constructible_v<T>) {
  if (this != addressof(that)) {
    if (that) emplace(std::move(*that));
    else reset();
  }
  return *this;
}
\end{codeblock}
\end{itemize}

\pnum
\recommended
\begin{itemize}
\item
If \tcode{\libconcept{copy_constructible}<T>} is \tcode{true},
\tcode{\exposid{movable-box}<T>} should store only a \tcode{T}
if either \tcode{T} models \libconcept{copyable}, or
\tcode{is_nothrow_move_constructible_v<T> \&\& is_nothrow_copy_constructible_v<T>}
is \tcode{true}.
\item
Otherwise, \tcode{\exposid{movable-box}<T>} should store only a \tcode{T}
if either \tcode{T} models \libconcept{movable} or
\tcode{is_nothrow_move_constructible_v<T>} is \tcode{true}.
\end{itemize}

\rSec2[range.nonprop.cache]{Non-propagating cache}

\pnum
Some types in \ref{range.adaptors} are specified in terms of
an exposition-only class template \exposid{non-propagating-\brk{}cache}.
\tcode{\exposid{non-propagating-cache}<T>} behaves exactly like \tcode{optional<T>}
with the following differences:
\begin{itemize}
\item
\tcode{\exposid{non-propagating-cache}<T>} constrains its type parameter \tcode{T}
with \tcode{is_object_v<T>}.
\item
The copy constructor is equivalent to:
\begin{codeblock}
constexpr @\exposid{non-propagating-cache}@(const @\exposid{non-propagating-cache}@&) noexcept {}
\end{codeblock}
\item
The move constructor is equivalent to:
\begin{codeblock}
constexpr @\exposid{non-propagating-cache}@(@\exposid{non-propagating-cache}@&& other) noexcept {
  other.reset();
}
\end{codeblock}
\item
The copy assignment operator is equivalent to:
\begin{codeblock}
constexpr @\exposid{non-propagating-cache}@& operator=(const @\exposid{non-propagating-cache}@& other) noexcept {
  if (addressof(other) != this)
    reset();
  return *this;
}
\end{codeblock}
\item
The move assignment operator is equivalent to:
\begin{codeblock}
constexpr @\exposid{non-propagating-cache}@& operator=(@\exposid{non-propagating-cache}@&& other) noexcept {
  reset();
  other.reset();
  return *this;
}
\end{codeblock}
\item
\tcode{\exposid{non-propagating-cache}<T>} has an additional member function template
specified as follows:
\begin{itemdecl}
template<class I>
  constexpr T& @\exposid{emplace-deref}@(const I& i);    // \expos
\end{itemdecl}

\begin{itemdescr}
% Indenting the \item markers is necessary to avoid check errors complaining
% about missing pnum.
 \mandates
The declaration \tcode{T t(*i);} is well-formed
for some invented variable \tcode{t}.
\begin{note}
If \tcode{*i} is a prvalue of type \cv{} \tcode{T},
there is no requirement that it is movable\iref{dcl.init.general}.
\end{note}

 \effects
Calls \tcode{reset()}.
Then direct-non-list-initializes the contained value with \tcode{*i}.

 \ensures
\tcode{*this} contains a value.

 \returns
A reference to the new contained value.

 \throws
Any exception thrown by the initialization of the contained value.

 \remarks
If an exception is thrown during the initialization of \tcode{T},
\tcode{*this} does not contain a value, and
the previous value (if any) has been destroyed.
\end{itemdescr}
\end{itemize}

\pnum
\begin{note}
\exposid{non-propagating-cache} enables an input view
to temporarily cache values as it is iterated over.
\end{note}

\rSec2[range.adaptor.helpers]{Range adaptor helpers}

\begin{codeblock}
namespace std::ranges {
  template<class F, class Tuple>
  constexpr auto @\exposid{tuple-transform}@(F&& f, Tuple&& t) { // \expos
    return apply([&]<class... Ts>(Ts&&... elements) {
      return tuple<invoke_result_t<F&, Ts>...>(invoke(f, std::forward<Ts>(elements))...);
    }, std::forward<Tuple>(t));
  }

  template<class F, class Tuple>
  constexpr void @\exposid{tuple-for-each}@(F&& f, Tuple&& t) { // \expos
    apply([&]<class... Ts>(Ts&&... elements) {
      (static_cast<void>(invoke(f, std::forward<Ts>(elements))), ...);
    }, std::forward<Tuple>(t));
  }

  template<class T>
  constexpr T& @\exposid{as-lvalue}@(T&& t) {                   // \expos
    return static_cast<T&>(t);
  }

  template<bool Const, class... Views>
    concept @\defexposconceptnc{all-random-access}@ =                     // \expos
      (@\libconcept{random_access_range}@<@\exposid{maybe-const}@<Const, Views>> && ...);
  template<bool Const, class... Views>
    concept @\defexposconceptnc{all-bidirectional}@ =                     // \expos
      (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@<Const, Views>> && ...);
  template<bool Const, class... Views>
    concept @\defexposconceptnc{all-forward}@ =                           // \expos
      (@\libconcept{forward_range}@<@\exposid{maybe-const}@<Const, Views>> && ...);
}
\end{codeblock}

\rSec2[range.all]{All view}

\rSec3[range.all.general]{General}

\pnum
\indexlibrarymember{all}{views}%
\tcode{views::all} returns a view that includes all elements of
its range argument.

\pnum
The name \tcode{views::all} denotes a
range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E}, the expression
\tcode{views::all(E)} is expression-equivalent to:
\begin{itemize}
\item \tcode{\exposidnc{decay-copy}(E)} if the decayed type of \tcode{E}
models \libconcept{view}.

\item Otherwise, \tcode{ref_view\{E\}} if that expression is well-formed.

\item Otherwise, \tcode{owning_view\{E\}}.
\end{itemize}

\rSec3[range.ref.view]{Class template \tcode{ref_view}}

\pnum
\tcode{ref_view} is a view of the elements of some other range.
\indexlibraryglobal{ref_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{range}@ R>
    requires is_object_v<R>
  class ref_view : public view_interface<ref_view<R>> {
  private:
    R* @\exposid{r_}@;                      // \expos

  public:
    template<@\exposconcept{different-from}@<ref_view> T>
      requires @\seebelow@
    constexpr ref_view(T&& t);

    constexpr R& base() const { return *@\exposid{r_}@; }

    constexpr iterator_t<R> begin() const { return ranges::begin(*@\exposid{r_}@); }
    constexpr sentinel_t<R> end() const { return ranges::end(*@\exposid{r_}@); }

    constexpr bool empty() const
      requires requires { ranges::empty(*@\exposid{r_}@); }
    { return ranges::empty(*@\exposid{r_}@); }

    constexpr auto size() const requires @\libconcept{sized_range}@<R>
    { return ranges::size(*@\exposid{r_}@); }

    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<R>
    { return ranges::reserve_hint(*@\exposid{r_}@); }

    constexpr auto data() const requires @\libconcept{contiguous_range}@<R>
    { return ranges::data(*@\exposid{r_}@); }
  };

  template<class R>
    ref_view(R&) -> ref_view<R>;
}
\end{codeblock}

\indexlibraryctor{ref_view}%
\begin{itemdecl}
template<@\exposconcept{different-from}@<ref_view> T>
  requires @\seebelow@
constexpr ref_view(T&& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{r_} with
\tcode{addressof(static_cast<R\&>(std::forward<T>(t)))}.

\pnum
\remarks
Let \tcode{\placeholder{FUN}} denote the exposition-only functions
\begin{codeblock}
void @\placeholder{FUN}@(R&);
void @\placeholder{FUN}@(R&&) = delete;
\end{codeblock}
The expression in the \grammarterm{requires-clause} is equivalent to:
\begin{codeblock}
@\libconcept{convertible_to}@<T, R&> && requires { @\placeholder{FUN}@(declval<T>()); }
\end{codeblock}
\end{itemdescr}

\rSec3[range.owning.view]{Class template \tcode{owning_view}}

\pnum
\tcode{owning_view} is a move-only view
of the elements of some other range.

\indexlibraryglobal{owning_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{range}@ R>
    requires @\libconcept{movable}@<R> && (!@\exposid{is-initializer-list}@<R>) // see \ref{range.refinements}
  class owning_view : public view_interface<owning_view<R>> {
  private:
    R @\exposid{r_}@ = R();         // \expos

  public:
    owning_view() requires @\libconcept{default_initializable}@<R> = default;
    constexpr owning_view(R&& t);

    owning_view(owning_view&&) = default;
    owning_view& operator=(owning_view&&) = default;

    constexpr R& base() & noexcept { return @\exposid{r_}@; }
    constexpr const R& base() const & noexcept { return @\exposid{r_}@; }
    constexpr R&& base() && noexcept { return std::move(@\exposid{r_}@); }
    constexpr const R&& base() const && noexcept { return std::move(@\exposid{r_}@); }

    constexpr iterator_t<R> begin() { return ranges::begin(@\exposid{r_}@); }
    constexpr sentinel_t<R> end() { return ranges::end(@\exposid{r_}@); }

    constexpr auto begin() const requires @\libconcept{range}@<const R>
    { return ranges::begin(@\exposid{r_}@); }
    constexpr auto end() const requires @\libconcept{range}@<const R>
    { return ranges::end(@\exposid{r_}@); }

    constexpr bool empty() requires requires { ranges::empty(@\exposid{r_}@); }
    { return ranges::empty(@\exposid{r_}@); }
    constexpr bool empty() const requires requires { ranges::empty(@\exposid{r_}@); }
    { return ranges::empty(@\exposid{r_}@); }

    constexpr auto size() requires @\libconcept{sized_range}@<R>
    { return ranges::size(@\exposid{r_}@); }
    constexpr auto size() const requires @\libconcept{sized_range}@<const R>
    { return ranges::size(@\exposid{r_}@); }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<R>
    { return ranges::reserve_hint(@\exposid{r_}@); }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const R>
    { return ranges::reserve_hint(@\exposid{r_}@); }

    constexpr auto data() requires @\libconcept{contiguous_range}@<R>
    { return ranges::data(@\exposid{r_}@); }
    constexpr auto data() const requires @\libconcept{contiguous_range}@<const R>
    { return ranges::data(@\exposid{r_}@); }
  };
}
\end{codeblock}

\indexlibraryctor{owning_view}%
\begin{itemdecl}
constexpr owning_view(R&& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{r_} with \tcode{std::move(t)}.
\end{itemdescr}

\rSec2[range.as.rvalue]{As rvalue view}

\rSec3[range.as.rvalue.overview]{Overview}

\pnum
\tcode{as_rvalue_view} presents a view of an underlying sequence
with the same behavior as the underlying sequence
except that its elements are rvalues.
Some generic algorithms can be called with an \tcode{as_rvalue_view}
to replace copying with moving.

\pnum
\indexlibrarymember{as_rvalue}{views}%
The name \tcode{views::as_rvalue} denotes
a range adaptor object\iref{range.adaptor.object}.
Let \tcode{E} be an expression and let \tcode{T} be \tcode{decltype((E))}.
The expression \tcode{views::as_rvalue(E)} is expression-equivalent to:
\begin{itemize}
\item
\tcode{views::all(E)} if
\tcode{T} models \libconcept{input_range} and
\tcode{\libconcept{same_as}<range_rvalue_reference_t<T>, range_reference_t<T>>} is \tcode{true}.
\item
Otherwise, \tcode{as_rvalue_view(E)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
vector<string> words = {"the", "quick", "brown", "fox", "ate", "a", "pterodactyl"};
vector<string> new_words;
ranges::copy(words | views::as_rvalue, back_inserter(new_words));
  // moves each string from \tcode{words} into \tcode{new_words}
\end{codeblock}
\end{example}

\rSec3[range.as.rvalue.view]{Class template \tcode{as_rvalue_view}}

\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class @\libglobal{as_rvalue_view}@ : public view_interface<as_rvalue_view<V>> {
    V @\exposid{base_}@ = V();      // \expos

  public:
    as_rvalue_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit as_rvalue_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>)
    { return move_iterator(ranges::begin(@\exposid{base_}@)); }
    constexpr auto begin() const requires @\libconcept{range}@<const V>
    { return move_iterator(ranges::begin(@\exposid{base_}@)); }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{common_range}@<V>) {
        return move_iterator(ranges::end(@\exposid{base_}@));
      } else {
        return move_sentinel(ranges::end(@\exposid{base_}@));
      }
    }
    constexpr auto end() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{common_range}@<const V>) {
        return move_iterator(ranges::end(@\exposid{base_}@));
      } else {
        return move_sentinel(ranges::end(@\exposid{base_}@));
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V> { return ranges::size(@\exposid{base_}@); }
    constexpr auto size() const requires @\libconcept{sized_range}@<const V> { return ranges::size(@\exposid{base_}@); }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
  };

  template<class R>
    as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{as_rvalue_view}%
\begin{itemdecl}
constexpr explicit as_rvalue_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec2[range.filter]{Filter view}

\rSec3[range.filter.overview]{Overview}

\pnum
\tcode{filter_view} presents a view of the elements
of an underlying sequence that satisfy a predicate.

\pnum
\indexlibrarymember{filter}{views}%
The name \tcode{views::filter} denotes a
range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{P},
the expression \tcode{views::filter(E, P)} is expression-equivalent to
\tcode{filter_view(E, P)}.

\pnum
\begin{example}
\begin{codeblock}
vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
auto evens = views::filter(is, [](int i) { return 0 == i % 2; });
for (int i : evens)
  cout << i << ' '; // prints \tcode{0 2 4 6}
\end{codeblock}
\end{example}

\rSec3[range.filter.view]{Class template \tcode{filter_view}}

\indexlibraryglobal{filter_view}%
\indexlibrarymember{base}{filter_view}%
\indexlibrarymember{end}{filter_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@<iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  class filter_view : public view_interface<filter_view<V, Pred>> {
  private:
    V @\exposid{base_}@ = V();                              // \expos
    @\exposidnc{movable-box}@<Pred> @\exposid{pred_}@;                    // \expos

    // \ref{range.filter.iterator}, class \tcode{filter_view::\exposid{iterator}}
    template<bool> class @\exposid{iterator}@;              // \expos

    // \ref{range.filter.sentinel}, class \tcode{filter_view::\exposid{sentinel}}
    template<bool> class @\exposid{sentinel}@;              // \expos

  public:
    filter_view() requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pred> = default;
    constexpr explicit filter_view(V base, Pred pred);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr const Pred& pred() const;

    constexpr @\exposid{iterator}@<false> begin();
    constexpr @\exposid{iterator}@<true> begin() const
      requires (@\libconcept{input_range}@<const V> && !@\libconcept{forward_range}@<const V> &&
                @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<const V>>);

    constexpr auto end() {
      if constexpr (@\libconcept{common_range}@<V>)
        return @\exposid{iterator}@<false>{*this, ranges::end(@\exposid{base_}@)};
      else
        return @\exposid{sentinel}@<false>{*this};
    }
    constexpr @\exposid{sentinel}@<true> end() const
      requires (@\libconcept{input_range}@<const V> && !@\libconcept{forward_range}@<const V> &&
                @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<const V>>) {
      return @\exposid{sentinel}@<true>{*this};
    }
  };

  template<class R, class Pred>
    filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
}
\end{codeblock}

\indexlibraryctor{filter_view}%
\begin{itemdecl}
constexpr explicit filter_view(V base, Pred pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and initializes
\exposid{pred_} with \tcode{std::move(pred)}.
\end{itemdescr}

\indexlibrarymember{pred}{filter_view}%
\begin{itemdecl}
constexpr const Pred& pred() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{pred_};}
\end{itemdescr}

\indexlibrarymember{begin}{filter_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<false> begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{pred_}.has_value()} is \tcode{true}.

\pnum
\returns
\tcode{\{*this, ranges::find_if(\exposid{base_}, ref(*\exposid{pred_}))\}}.

\pnum
\remarks
In order to provide the amortized constant time complexity required by
the \libconcept{range} concept
when \tcode{filter_view} models \libconcept{forward_range},
this function caches the result within the
\tcode{filter_view} for use on subsequent calls.
\end{itemdescr}

\indexlibrarymember{begin}{filter_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<true> begin() const
  requires (@\libconcept{input_range}@<const V> && !@\libconcept{forward_range}@<const V> &&
            @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<const V>>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{pred_}.has_value()} is \tcode{true}.

\pnum
\returns
\tcode{\{*this, ranges::find_if(\exposid{base_}, ref(*\exposid{pred_}))\}}.
\begin{note}
This function does not cache the result within the \tcode{filter_view}.
\end{note}
\end{itemdescr}

\rSec3[range.filter.iterator]{Class template \tcode{filter_view::\exposid{iterator}}}

\indexlibraryglobal{filter_view::\exposid{iterator}}%
\indexlibrarymember{iterator}{filter_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@<iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  template<bool Const>
  class filter_view<V, Pred>::@\exposid{iterator}@ {
  private:
    using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@<Const, filter_view>;                     // \expos
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                                 // \expos
    iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>();                     // \expos
    @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr;                                          // \expos
    constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, iterator_t<@\exposidnc{Base}@> current);       // \expos

  public:
    using iterator_concept  = @\seebelownc@;
    using iterator_category = @\seebelownc@;                                // not always present
    using value_type        = range_value_t<@\exposidnc{Base}@>;
    using difference_type   = range_difference_t<@\exposidnc{Base}@>;

    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposidnc{Base}@>> = default;
    constexpr @\exposid{iterator}@(iterator<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposidnc{Base}@>>;

    constexpr const iterator_t<@\exposidnc{Base}@>& base() const & noexcept;
    constexpr iterator_t<@\exposidnc{Base}@> base() &&;
    constexpr range_reference_t<@\exposidnc{Base}@> operator*() const;
    constexpr iterator_t<@\exposidnc{Base}@> operator->() const
      requires @\exposconcept{has-arrow}@<iterator_t<@\exposidnc{Base}@>> && @\libconcept{copyable}@<iterator_t<@\exposidnc{Base}@>>;

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposidnc{Base}@>;

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposidnc{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposidnc{Base}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<iterator_t<@\exposidnc{Base}@>>;

    friend constexpr range_rvalue_reference_t<@\exposidnc{Base}@> iter_move(const @\exposid{iterator}@& i)
      noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));

    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
      requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposidnc{Base}@>>;
  };
}
\end{codeblock}

\pnum
\begin{note}
Modification of the element a \tcode{filter_view::\exposid{iterator}} denotes
can result in undefined behavior
if the underlying range is a \libconcept{forward_range} and
the resulting value does not satisfy the filter predicate
when the predicate is next evaluated for that element\iref{concepts.equality}.
\end{note}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item If \tcode{Const} is \tcode{true},
then \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.

\item Otherwise, if \tcode{V} models \libconcept{bidirectional_range}, then
\tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.

\item Otherwise, if \tcode{V} models \libconcept{forward_range}, then
\tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.

\item Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if \exposid{Base} models \libconcept{forward_range}.
In that case,
\tcode{\exposid{iterator}::iterator_category} is defined as follows:
\begin{itemize}
\item Let \tcode{C} denote the type
\tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}.

\item If \tcode{C} models
\tcode{\libconcept{derived_from}<bidirectional_iterator_tag>},
then \tcode{iterator_category} denotes \tcode{bi\-directional_iterator_tag}.

\item Otherwise, if  \tcode{C} models
\tcode{\libconcept{derived_from}<forward_iterator_tag>},
then \tcode{iterator_category} denotes \tcode{forward_iterator_tag}.

\item Otherwise, \tcode{iterator_category} denotes \tcode{C}.
\end{itemize}

\indexlibraryctor{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)} and
\exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibraryctor{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and
\exposid{current_} with \tcode{std::move(i.\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{base}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{current_};}
\end{itemdescr}

\indexlibrarymember{base}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return std::move(\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{operator*}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr range_reference_t<@\exposid{Base}@> operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator->}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> operator->() const
  requires @\exposconcept{has-arrow}@<iterator_t<@\exposid{Base}@>> && @\libconcept{copyable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator++}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ = ranges::find_if(std::move(++@\exposid{current_}@), ranges::end(@\exposid{parent_}@->@\exposid{base_}@),
                           ref(*@\exposid{parent_}@->@\exposid{pred_}@));
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
do
  --@\exposid{current_}@;
while (!invoke(*@\exposid{parent_}@->@\exposid{pred_}@, *@\exposid{current_}@));
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{iter_move}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
  noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{iter_swap}{filter_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
  requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}.
\end{itemdescr}

\rSec3[range.filter.sentinel]{Class template \tcode{filter_view::\exposid{sentinel}}}

\indexlibraryglobal{filter_view::\exposid{sentinel}}%
\indexlibrarymember{sentinel}{filter_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@<iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  template<bool Const>
  class filter_view<V, Pred>::@\exposid{sentinel}@ {
  private:
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                         // \expos
    sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>();                 // \expos
    constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{Parent}@& parent);                // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> other)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposidnc{Base}@>>;

    constexpr sentinel_t<@\exposidnc{Base}@> base() const;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposidnc{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
      friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
  };
}
\end{codeblock}

\indexlibraryctor{filter_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> other)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposidnc{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}.
\end{itemdescr}

\indexlibraryctor{filter_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}.
\end{itemdescr}

\indexlibrarymember{base}{filter_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr sentinel_t<@\exposidnc{Base}@> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator==}{filter_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposidnc{Base}@>, iterator_t<@\exposid{maybe-const}@ <OtherConst, V>>>
  friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};}
\end{itemdescr}

\rSec2[range.transform]{Transform view}

\rSec3[range.transform.overview]{Overview}

\pnum
\tcode{transform_view} presents
a view of an underlying sequence after
applying a transformation function to each element.

\pnum
\indexlibrarymember{transform}{views}%
The name \tcode{views::transform} denotes a
range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F}, the expression
\tcode{views::transform(E, F)} is expression-equivalent to
\tcode{transform_view(E, F)}.

\pnum
\begin{example}
\begin{codeblock}
vector<int> is{ 0, 1, 2, 3, 4 };
auto squares = views::transform(is, [](int i) { return i * i; });
for (int i : squares)
  cout << i << ' '; // prints \tcode{0 1 4 9 16}
\end{codeblock}
\end{example}

\rSec3[range.transform.view]{Class template \tcode{transform_view}}

\indexlibraryglobal{transform_view}%
\indexlibrarymember{base}{transform_view}%
\indexlibrarymember{size}{transform_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F>
    requires @\libconcept{view}@<V> && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, range_reference_t<V>> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<V>>>
  class transform_view : public view_interface<transform_view<V, F>> {
  private:
    // \ref{range.transform.iterator}, class template \tcode{transform_view::\exposid{iterator}}
    template<bool> struct @\exposid{iterator}@;             // \expos

    // \ref{range.transform.sentinel}, class template \tcode{transform_view::\exposid{sentinel}}
    template<bool> struct @\exposid{sentinel}@;             // \expos

    V @\exposid{base_}@ = V();                              // \expos
    @\placeholdernc{movable-box}@<F> @\exposid{fun_}@;                        // \expos

  public:
    transform_view() requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<F> = default;
    constexpr explicit transform_view(V base, F fun);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr @\exposid{iterator}@<false> begin();
    constexpr @\exposid{iterator}@<true> begin() const
      requires @\libconcept{range}@<const V> &&
               @\libconcept{regular_invocable}@<const F&, range_reference_t<const V>>;

    constexpr @\exposid{sentinel}@<false> end();
    constexpr @\exposid{iterator}@<false> end() requires @\libconcept{common_range}@<V>;
    constexpr @\exposid{sentinel}@<true> end() const
      requires @\libconcept{range}@<const V> &&
               @\libconcept{regular_invocable}@<const F&, range_reference_t<const V>>;
    constexpr @\exposid{iterator}@<true> end() const
      requires @\libconcept{common_range}@<const V> &&
               @\libconcept{regular_invocable}@<const F&, range_reference_t<const V>>;

    constexpr auto size() requires @\libconcept{sized_range}@<V> { return ranges::size(@\exposid{base_}@); }
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>
    { return ranges::size(@\exposid{base_}@); }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
  };

  template<class R, class F>
    transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
}
\end{codeblock}

\indexlibraryctor{transform_view}%
\begin{itemdecl}
constexpr explicit transform_view(V base, F fun);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{fun_} with \tcode{std::move(fun)}.
\end{itemdescr}

\indexlibrarymember{begin}{transform_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<false> begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{iterator}@<false>{*this, ranges::begin(@\exposid{base_}@)};
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{begin}{transform_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<true> begin() const
  requires @\libconcept{range}@<const V> &&
           @\libconcept{regular_invocable}@<const F&, range_reference_t<const V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{iterator}@<true>{*this, ranges::begin(@\exposid{base_}@)};
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{transform_view}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@<false> end();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{sentinel}@<false>{ranges::end(@\exposid{base_}@)};
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{transform_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<false> end() requires @\libconcept{common_range}@<V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{iterator}@<false>{*this, ranges::end(@\exposid{base_}@)};
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{transform_view}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@<true> end() const
  requires @\libconcept{range}@<const V> &&
           @\libconcept{regular_invocable}@<const F&, range_reference_t<const V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{sentinel}@<true>{ranges::end(@\exposid{base_}@)};
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{transform_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<true> end() const
  requires @\libconcept{common_range}@<const V> &&
           @\libconcept{regular_invocable}@<const F&, range_reference_t<const V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{iterator}@<true>{*this, ranges::end(@\exposid{base_}@)};
\end{codeblock}
\end{itemdescr}

\rSec3[range.transform.iterator]{Class template \tcode{transform_view::\exposid{iterator}}}

\indexlibraryglobal{transform_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F>
    requires @\libconcept{view}@<V> && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, range_reference_t<V>> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<V>>>
  template<bool Const>
  class transform_view<V, F>::@\exposid{iterator}@ {
  private:
    using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@<Const, transform_view>;                  // \expos
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                                 // \expos
    iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>();                     // \expos
    @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr;                                          // \expos
    constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposidnc{Base}@> current);       // \expos

  public:
    using iterator_concept  = @\seebelownc@;
    using iterator_category = @\seebelownc@;                        // not always present
    using value_type        =
      remove_cvref_t<invoke_result_t<@\exposidnc{maybe-const}@<Const, F>&, range_reference_t<@\exposid{Base}@>>>;
    using difference_type   = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposid{Base}@>> = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
    constexpr iterator_t<@\exposid{Base}@> base() &&;

    constexpr decltype(auto) operator*() const
      noexcept(noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *@\exposid{current_}@))) {
      return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *@\exposid{current_}@);
    }

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr decltype(auto) operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> {
      return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, @\exposid{current_}@[n]);
    }

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item If \exposid{Base} models \libconcept{random_access_range}, then
\tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.

\item Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, then
\tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.

\item Otherwise, if \exposid{Base} models \libconcept{forward_range}, then
\tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.

\item Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if \exposid{Base} models \libconcept{forward_range}.
In that case,
\tcode{\exposid{iterator}::iterator_category} is defined as follows:
Let \tcode{C} denote the type
\tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}.
\begin{itemize}
\item
If \tcode{is_reference_v<invoke_result_t<\exposidnc{maybe-const}<Const, F>\&, range_reference_t<\exposid{Base}>>>}
is \tcode{true}, then
\begin{itemize}
\item
if \tcode{C} models \tcode{\libconcept{derived_from}<contiguous_iterator_tag>},
\tcode{iterator_category} denotes \tcode{random_access_iterator_tag};

\item
otherwise,
\tcode{iterator_category} denotes \tcode{C}.
\end{itemize}

\item
Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\end{itemize}

\indexlibrarymember{iterator}{transform_view::\exposid{iterator}}
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)} and
\exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibraryctor{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and
\exposid{parent_} with \tcode{i.\exposid{parent_}}.
\end{itemdescr}

\indexlibrarymember{base}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{current_};}
\end{itemdescr}

\indexlibrarymember{base}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return std::move(\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{operator++}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator++}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ += n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ -= n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator<}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} < y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator>}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator+}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}\{*i.\exposid{parent_}, i.\exposid{current_} + n\};}
\end{itemdescr}

\indexlibrarymember{operator-}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}\{*i.\exposid{parent_}, i.\exposid{current_} - n\};}
\end{itemdescr}

\indexlibrarymember{operator-}{transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};}
\end{itemdescr}


\rSec3[range.transform.sentinel]{Class template \tcode{transform_view::\exposid{sentinel}}}

\indexlibraryglobal{transform_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F>
    requires @\libconcept{view}@<V> && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, range_reference_t<V>> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<V>>>
  template<bool Const>
  class transform_view<V, F>::@\exposid{sentinel}@ {
  private:
    using @\exposid{Parent}@ = @\exposid{maybe-const}@<Const, transform_view>;  // \expos
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                 // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();         // \expos
    constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);  // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr sentinel_t<@\exposid{Base}@> base() const;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<OtherConst>& x);
  };
}
\end{codeblock}

\indexlibraryctor{transform_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end}.
\end{itemdescr}

\indexlibraryctor{transform_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{base}{transform_view::\exposid{sentinel}}
\begin{itemdecl}
constexpr sentinel_t<@\exposid{Base}@> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator==}{transform_view::\exposid{sentinel}}
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{transform_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{transform_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<OtherConst>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_};}
\end{itemdescr}

\rSec2[range.take]{Take view}

\rSec3[range.take.overview]{Overview}

\pnum
\tcode{take_view} produces a view of the first $N$ elements
from another view, or all the elements if the adapted
view contains fewer than $N$.

\pnum
\indexlibrarymember{take}{views}%
The name \tcode{views::take} denotes a
range adaptor object\iref{range.adaptor.object}.
Let \tcode{E} and \tcode{F} be expressions,
let \tcode{T} be \tcode{remove_cvref_t<decltype((E))>}, and
let \tcode{D} be \tcode{range_difference_t<decltype((E))>}.
If \tcode{decltype((F))} does not model
\tcode{\libconcept{convertible_to}<D>},
\tcode{views::take(E, F)} is ill-formed.
Otherwise, the expression \tcode{views::take(E, F)}
is expression-equivalent to:

\begin{itemize}
\item
If \tcode{T} is a specialization
of \tcode{empty_view}\iref{range.empty.view},
then \tcode{((void)F, \exposidnc{decay-copy}(E))},
except that the evaluations of \tcode{E} and \tcode{F}
are indeterminately sequenced.

\item
Otherwise, if \tcode{T} is a specialization of
\tcode{optional} and \tcode{T} models \libconcept{view}, then
\tcode{(static_cast<D>(F) == D() ? ((void)E, T()) : \exposidnc{decay-copy}(E))}.

\item
Otherwise, if \tcode{T} models
\libconcept{random_access_range} and \libconcept{sized_range}
and is a specialization of
\tcode{span}\iref{views.span},
\tcode{basic_string_view}\iref{string.view}, or
\tcode{subrange}\iref{range.subrange},
then
\tcode{U(ranges::begin(E),
ranges::be\-gin(E) + std::min<D>(ranges::distance(E), F))},
except that \tcode{E} is evaluated only once,
where \tcode{U} is a type determined as follows:

\begin{itemize}
\item if \tcode{T} is a specialization of \tcode{span},
then \tcode{U} is \tcode{span<typename T::element_type>};
\item otherwise, if \tcode{T} is a specialization of \tcode{basic_string_view},
then \tcode{U} is \tcode{T};
\item otherwise, \tcode{T} is a specialization of \tcode{subrange}, and
\tcode{U} is \tcode{subrange<iterator_t<T>>};
\end{itemize}

\item
otherwise, if \tcode{T} is
a specialization of \tcode{iota_view}\iref{range.iota.view}
that models \libconcept{random_access_range} and \libconcept{sized_range},
then
\tcode{iota_view(*ranges::begin(E),
*(ranges::begin(E) + std::\linebreak{}min<D>(ranges::distance(E), F)))},
except that \tcode{E} is evaluated only once.

\item
Otherwise, if \tcode{T} is
a specialization of \tcode{repeat_view}\iref{range.repeat.view}:
\begin{itemize}
\item
if \tcode{T} models \libconcept{sized_range},
then
\begin{codeblock}
views::repeat(*E.@\exposid{value_}@, std::min<D>(ranges::distance(E), F))
\end{codeblock}
except that \tcode{E} is evaluated only once;
\item
otherwise, \tcode{views::repeat(*E.\exposid{value_}, static_cast<D>(F))}.
\end{itemize}

\item
Otherwise, \tcode{take_view(E, F)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
vector<int> is{0,1,2,3,4,5,6,7,8,9};
for (int i : is | views::take(5))
  cout << i << ' '; // prints \tcode{0 1 2 3 4}
\end{codeblock}
\end{example}

\rSec3[range.take.view]{Class template \tcode{take_view}}

\indexlibraryglobal{take_view}%
\indexlibrarymember{base}{take_view}%
\indexlibrarymember{begin}{take_view}%
\indexlibrarymember{end}{take_view}%
\indexlibrarymember{size}{take_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
  class take_view : public view_interface<take_view<V>> {
  private:
    V @\exposid{base_}@ = V();                                      // \expos
    range_difference_t<V> @\exposid{count_}@ = 0;                   // \expos

    // \ref{range.take.sentinel}, class template \tcode{take_view::\exposid{sentinel}}
    template<bool> class @\exposid{sentinel}@;                      // \expos

  public:
    take_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit take_view(V base, range_difference_t<V> count);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{sized_range}@<V>) {
        if constexpr (@\libconcept{random_access_range}@<V>) {
          return ranges::begin(@\exposid{base_}@);
        } else {
          auto sz = range_difference_t<V>(size());
          return counted_iterator(ranges::begin(@\exposid{base_}@), sz);
        }
      } else if constexpr (@\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>) {
        auto it = ranges::begin(@\exposid{base_}@);
        auto sz = std::min(@\exposid{count_}@, ranges::end(@\exposid{base_}@) - it);
        return counted_iterator(std::move(it), sz);
      } else {
        return counted_iterator(ranges::begin(@\exposid{base_}@), @\exposid{count_}@);
      }
    }

    constexpr auto begin() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{sized_range}@<const V>) {
        if constexpr (@\libconcept{random_access_range}@<const V>) {
          return ranges::begin(@\exposid{base_}@);
        } else {
          auto sz = range_difference_t<const V>(size());
          return counted_iterator(ranges::begin(@\exposid{base_}@), sz);
        }
      } else if constexpr (@\libconcept{sized_sentinel_for}@<sentinel_t<const V>, iterator_t<const V>>) {
        auto it = ranges::begin(@\exposid{base_}@);
        auto sz = std::min(@\exposid{count_}@, ranges::end(@\exposid{base_}@) - it);
        return counted_iterator(std::move(it), sz);
      } else {
        return counted_iterator(ranges::begin(@\exposid{base_}@), @\exposid{count_}@);
      }
    }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{sized_range}@<V>) {
        if constexpr (@\libconcept{random_access_range}@<V>)
          return ranges::begin(@\exposid{base_}@) + range_difference_t<V>(size());
        else
          return default_sentinel;
      } else if constexpr (@\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>) {
        return default_sentinel;
      } else {
        return @\exposid{sentinel}@<false>{ranges::end(@\exposid{base_}@)};
      }
    }

    constexpr auto end() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{sized_range}@<const V>) {
        if constexpr (@\libconcept{random_access_range}@<const V>)
          return ranges::begin(@\exposid{base_}@) + range_difference_t<const V>(size());
        else
          return default_sentinel;
      } else if constexpr (@\libconcept{sized_sentinel_for}@<sentinel_t<const V>, iterator_t<const V>>) {
        return default_sentinel;
      } else {
        return @\exposid{sentinel}@<true>{ranges::end(@\exposid{base_}@)};
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V> {
      auto n = ranges::size(@\exposid{base_}@);
      return ranges::min(n, static_cast<decltype(n)>(@\exposid{count_}@));
    }

    constexpr auto size() const requires @\libconcept{sized_range}@<const V> {
      auto n = ranges::size(@\exposid{base_}@);
      return ranges::min(n, static_cast<decltype(n)>(@\exposid{count_}@));
    }

    constexpr auto reserve_hint() {
      if constexpr (@\libconcept{approximately_sized_range}@<V>) {
        auto n = static_cast<range_difference_t<V>>(ranges::reserve_hint(@\exposid{base_}@));
        return @\exposid{to-unsigned-like}@(ranges::min(n, @\exposid{count_}@));
      }
      return @\exposid{to-unsigned-like}@(@\exposid{count_}@);
    }

    constexpr auto reserve_hint() const {
      if constexpr (@\libconcept{approximately_sized_range}@<const V>) {
        auto n = static_cast<range_difference_t<const V>>(ranges::reserve_hint(@\exposid{base_}@));
        return @\exposid{to-unsigned-like}@(ranges::min(n, @\exposid{count_}@));
      }
      return @\exposid{to-unsigned-like}@(@\exposid{count_}@);
    }
  };

  template<class R>
    take_view(R&&, range_difference_t<R>)
      -> take_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{take_view}%
\begin{itemdecl}
constexpr explicit take_view(V base, range_difference_t<V> count);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{count >= 0} is \tcode{true}.

\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{count_} with \tcode{count}.
\end{itemdescr}

\rSec3[range.take.sentinel]{Class template \tcode{take_view::\exposid{sentinel}}}

\indexlibraryglobal{take_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
  template<bool Const>
  class take_view<V>::@\exposid{sentinel}@ {
  private:
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                                     // \expos
    template<bool OtherConst>
      using @\exposid{CI}@ = counted_iterator<iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>;  // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();                             // \expos
    constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);                      // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr sentinel_t<@\exposid{Base}@> base() const;

    friend constexpr bool operator==(const @\exposid{CI}@<Const>& y, const @\exposid{sentinel}@& x);

    template<bool OtherConst = !Const>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{CI}@<OtherConst>& y, const @\exposid{sentinel}@& x);
  };
}
\end{codeblock}

\indexlibraryctor{take_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end}.
\end{itemdescr}

\indexlibraryctor{take_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{base}{take_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr sentinel_t<@\exposid{Base}@> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator==}{take_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{CI}@<Const>& y, const @\exposid{sentinel}@& x);

template<bool OtherConst = !Const>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{CI}@<OtherConst>& y, const @\exposid{sentinel}@& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return y.count() == 0 || y.base() == x.\exposid{end_};}
\end{itemdescr}

\rSec2[range.take.while]{Take while view}

\rSec3[range.take.while.overview]{Overview}

\pnum
Given a unary predicate \tcode{pred} and a view \tcode{r},
\tcode{take_while_view} produces a view
of the range \range{ranges::be\-gin(r)}{ranges::find_if_not(r, pred)}.

\indexlibraryglobal{take_while}%
\pnum
\indexlibrarymember{take_while}{views}%
The name \tcode{views::take_while} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expression \tcode{views::take_while(E, F)}
is expression-equivalent to \tcode{take_while_view(E, F)}.

\pnum
\begin{example}
\begin{codeblock}
auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
auto small = [](const auto x) noexcept { return x < 5; };
auto small_ints = views::istream<int>(input) | views::take_while(small);
for (const auto i : small_ints) {
  cout << i << ' ';                             // prints \tcode{0 1 2 3 4}
}
auto i = 0;
input >> i;
cout << i;                                      // prints \tcode{6}
\end{codeblock}
\end{example}

\rSec3[range.take.while.view]{Class template \tcode{take_while_view}}

\indexlibraryglobal{take_while_view}%
\indexlibrarymember{base}{take_while_view}%
\indexlibrarymember{begin}{take_while_view}%
\indexlibrarymember{end}{take_while_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V, class Pred>
    requires @\libconcept{input_range}@<V> && is_object_v<Pred> &&
             @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<V>>
  class take_while_view : public view_interface<take_while_view<V, Pred>> {
    // \ref{range.take.while.sentinel}, class template \tcode{take_while_view::\exposid{sentinel}}
    template<bool> class @\exposidnc{sentinel}@;                      // \expos

    V @\exposid{base_}@ = V();                                      // \expos
    @\exposidnc{movable-box}@<Pred> @\exposid{pred_}@;                            // \expos

  public:
    take_while_view() requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pred> = default;
    constexpr explicit take_while_view(V base, Pred pred);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr const Pred& pred() const;

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>)
    { return ranges::begin(@\exposid{base_}@); }

    constexpr auto begin() const
      requires @\libconcept{range}@<const V> &&
               @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<const V>>
    { return ranges::begin(@\exposid{base_}@); }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>)
    { return @\exposid{sentinel}@<false>(ranges::end(@\exposid{base_}@), addressof(*@\exposid{pred_}@)); }

    constexpr auto end() const
      requires @\libconcept{range}@<const V> &&
               @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<const V>>
    { return @\exposid{sentinel}@<true>(ranges::end(@\exposid{base_}@), addressof(*@\exposid{pred_}@)); }
  };

  template<class R, class Pred>
    take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
}
\end{codeblock}

\indexlibraryctor{take_while_view}%
\begin{itemdecl}
constexpr explicit take_while_view(V base, Pred pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{pred_} with \tcode{std::move(pred)}.
\end{itemdescr}

\indexlibrarymember{pred}{take_while_view}%
\begin{itemdecl}
constexpr const Pred& pred() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{pred_};}
\end{itemdescr}

\rSec3[range.take.while.sentinel]{Class template \tcode{take_while_view::\exposid{sentinel}}}

\indexlibraryglobal{take_while_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V, class Pred>
    requires @\libconcept{input_range}@<V> && is_object_v<Pred> &&
             @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<V>>
  template<bool Const>
  class take_while_view<V, Pred>::@\exposidnc{sentinel}@ {
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                                        // \expos

    sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>();                                 // \expos
    const Pred* @\exposid{pred_}@ = nullptr;                                                // \expos
    constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end, const Pred* pred);       // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr sentinel_t<@\exposid{Base}@> base() const { return @\exposid{end_}@; }

    friend constexpr bool operator==(const iterator_t<@\exposid{Base}@>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst = !Const>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const iterator_t<@\exposid{maybe-const}@<OtherConst, V>>& x,
                                     const @\exposid{sentinel}@& y);
  };
}
\end{codeblock}

\indexlibraryctor{take_while_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end, const Pred* pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end} and \exposid{pred_} with \tcode{pred}.
\end{itemdescr}

\indexlibraryctor{take_while_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})} and
\exposid{pred_} with \tcode{s.\exposid{pred_}}.
\end{itemdescr}

\indexlibrarymember{operator==}{take_while_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr bool operator==(const iterator_t<@\exposid{Base}@>& x, const @\exposid{sentinel}@& y);

template<bool OtherConst = !Const>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const iterator_t<@\exposid{maybe-const}@<OtherConst, V>>& x,
                                 const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return y.\exposid{end_} == x || !invoke(*y.\exposid{pred_}, *x);}
\end{itemdescr}

\rSec2[range.drop]{Drop view}

\rSec3[range.drop.overview]{Overview}

\pnum
\tcode{drop_view} produces a view
excluding the first $N$ elements from another view, or
an empty range if the adapted view contains fewer than $N$ elements.

\pnum
\indexlibrarymember{drop}{views}%
The name \tcode{views::drop} denotes
a range adaptor object\iref{range.adaptor.object}.
Let \tcode{E} and \tcode{F} be expressions,
let \tcode{T} be \tcode{remove_cvref_t<decltype((E))>}, and
let \tcode{D} be \tcode{range_difference_t<decltype((E))>}.
If \tcode{decltype((F))} does not model
\tcode{\libconcept{convertible_to}<D>},
\tcode{views::drop(E, F)} is ill-formed.
Otherwise, the expression \tcode{views::drop(E, F)}
is expression-equivalent to:

\begin{itemize}
\item
If \tcode{T} is a specialization of
\tcode{empty_view}\iref{range.empty.view},
then \tcode{((void)F, \exposidnc{decay-copy}(E))},
except that the evaluations of \tcode{E} and \tcode{F}
are indeterminately sequenced.

\item
Otherwise, if \tcode{T} is a specialization of \tcode{optional}
and \tcode{T} models \libconcept{view}, then
\tcode{(static_cast<D>(F) == D() ? \exposidnc{decay-copy}(E) : ((void)E, T()))}.

\item
Otherwise, if \tcode{T} models
\libconcept{random_access_range} and \libconcept{sized_range}
and is
\begin{itemize}
\item a specialization of \tcode{span}\iref{views.span},
\item a specialization of \tcode{basic_string_view}\iref{string.view},
\item a specialization of \tcode{iota_view}\iref{range.iota.view}, or
\item a specialization of \tcode{subrange}\iref{range.subrange}
where \tcode{T::\exposid{StoreSize}} is \tcode{false},
\end{itemize}
then \tcode{U(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::end(E))},
except that \tcode{E} is evaluated only once,
where \tcode{U} is \tcode{span<typename T::element_type>}
if \tcode{T} is a specialization of \tcode{span} and \tcode{T} otherwise.

\item
Otherwise,
if \tcode{T} is
a specialization of \tcode{subrange}
that models \libconcept{random_access_range} and \libconcept{sized_range},
then
\tcode{T(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::\linebreak{}end(E),
\exposid{to-unsigned-like}(ranges::distance(E) -
std::min<D>(ranges::distance(E), F)))},
except that \tcode{E} and \tcode{F} are each evaluated only once.

\item
Otherwise, if \tcode{T} is
a specialization of \tcode{repeat_view}\iref{range.repeat.view}:
\begin{itemize}
\item
if \tcode{T} models \libconcept{sized_range},
then
\begin{codeblock}
views::repeat(*E.@\exposid{value_}@, ranges::distance(E) - std::min<D>(ranges::distance(E), F))
\end{codeblock}
except that \tcode{E} is evaluated only once;
\item
otherwise, \tcode{((void)F, \exposidnc{decay-copy}(E))},
except that the evaluations of \tcode{E} and \tcode{F} are indeterminately sequenced.
\end{itemize}

\item
Otherwise, \tcode{drop_view(E, F)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
auto ints = views::iota(0) | views::take(10);
for (auto i : ints | views::drop(5)) {
  cout << i << ' ';                             // prints \tcode{5 6 7 8 9}
}
\end{codeblock}
\end{example}

\rSec3[range.drop.view]{Class template \tcode{drop_view}}

\indexlibraryglobal{drop_view}%
\indexlibrarymember{base}{drop_view}%
\indexlibrarymember{end}{drop_view}%
\indexlibrarymember{size}{drop_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
  class drop_view : public view_interface<drop_view<V>> {
  public:
    drop_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit drop_view(V base, range_difference_t<V> count);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin()
      requires (!(@\exposconcept{simple-view}@<V> &&
                  @\libconcept{random_access_range}@<const V> && @\libconcept{sized_range}@<const V>));
    constexpr auto begin() const
      requires @\libconcept{random_access_range}@<const V> && @\libconcept{sized_range}@<const V>;

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>)
    { return ranges::end(@\exposid{base_}@); }

    constexpr auto end() const requires @\libconcept{range}@<const V>
    { return ranges::end(@\exposid{base_}@); }

    constexpr auto size() requires @\libconcept{sized_range}@<V> {
      const auto s = ranges::size(@\exposid{base_}@);
      const auto c = static_cast<decltype(s)>(@\exposid{count_}@);
      return s < c ? 0 : s - c;
    }

    constexpr auto size() const requires @\libconcept{sized_range}@<const V> {
      const auto s = ranges::size(@\exposid{base_}@);
      const auto c = static_cast<decltype(s)>(@\exposid{count_}@);
      return s < c ? 0 : s - c;
    }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V> {
      const auto s = static_cast<range_difference_t<V>>(ranges::reserve_hint(@\exposid{base_}@));
      return @\exposid{to-unsigned-like}@(s < @\exposid{count_}@ ? 0 : s - @\exposid{count_}@);
    }

    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V> {
      const auto s = static_cast<range_difference_t<const V>>(ranges::reserve_hint(@\exposid{base_}@));
      return @\exposid{to-unsigned-like}@(s < @\exposid{count_}@ ? 0 : s - @\exposid{count_}@);
    }

  private:
    V @\exposid{base_}@ = V();                              // \expos
    range_difference_t<V> @\exposid{count_}@ = 0;           // \expos
  };

  template<class R>
    drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{drop_view}%
\begin{itemdecl}
constexpr explicit drop_view(V base, range_difference_t<V> count);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{count >= 0} is \tcode{true}.

\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{count_} with \tcode{count}.
\end{itemdescr}

\indexlibrarymember{begin}{drop_view}%
\begin{itemdecl}
constexpr auto begin()
  requires (!(@\exposconcept{simple-view}@<V> &&
              @\libconcept{random_access_range}@<const V> && @\libconcept{sized_range}@<const V>));
constexpr auto begin() const
  requires @\libconcept{random_access_range}@<const V> && @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{ranges::next(ranges::begin(\exposid{base_}), \exposid{count_}, ranges::end(\exposid{base_}))}.

\pnum
\remarks
In order to provide the amortized constant-time complexity required
by the \libconcept{range} concept
when \tcode{drop_view} models \libconcept{forward_range},
the first overload caches the result within the \tcode{drop_view}
for use on subsequent calls.
\begin{note}
Without this,
applying a \tcode{reverse_view} over a \tcode{drop_view}
would have quadratic iteration complexity.
\end{note}
\end{itemdescr}

\rSec2[range.drop.while]{Drop while view}

\rSec3[range.drop.while.overview]{Overview}

\pnum
Given a unary predicate \tcode{pred} and a view \tcode{r},
\tcode{drop_while_view} produces a view
of the range \range{ranges::find_if_not(r, pred)}{ranges::end(r)}.

\pnum
\indexlibrarymember{drop_while}{views}%
The name \tcode{views::drop_while}
denotes a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expression \tcode{views::drop_while(E, F)}
is expression-equivalent to \tcode{drop_while_view(E, F)}.

\pnum
\begin{example}
\begin{codeblock}
constexpr auto source = "  \t   \t   \t   hello there"sv;
auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
auto skip_ws = views::drop_while(source, is_invisible);
for (auto c : skip_ws) {
  cout << c;                                    // prints \tcode{hello there} with no leading space
}
\end{codeblock}
\end{example}

\rSec3[range.drop.while.view]{Class template \tcode{drop_while_view}}

\indexlibraryglobal{drop_while_view}%
\indexlibrarymember{base}{drop_while_view}%
\indexlibrarymember{end}{drop_while_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V, class Pred>
    requires @\libconcept{input_range}@<V> && is_object_v<Pred> &&
             @\libconcept{indirect_unary_predicate}@<const Pred, iterator_t<V>>
  class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
  public:
    drop_while_view() requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pred> = default;
    constexpr explicit drop_while_view(V base, Pred pred);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr const Pred& pred() const;

    constexpr auto begin();

    constexpr auto end() { return ranges::end(@\exposid{base_}@); }

  private:
    V @\exposid{base_}@ = V();                                      // \expos
    @\placeholder{movable-box}@<Pred> @\exposid{pred_}@; @\itcorr[-1]@                           // \expos
  };

  template<class R, class Pred>
    drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
}
\end{codeblock}

\indexlibraryctor{drop_while_view}%
\begin{itemdecl}
constexpr explicit drop_while_view(V base, Pred pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{pred_} with \tcode{std::move(pred)}.
\end{itemdescr}

\indexlibrarymember{pred}{drop_while_view}%
\begin{itemdecl}
constexpr const Pred& pred() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{pred_};}
\end{itemdescr}

\indexlibrarymember{begin}{drop_while_view}%
\begin{itemdecl}
constexpr auto begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{pred_}.has_value()} is \tcode{true}.

\pnum
\returns
\tcode{ranges::find_if_not(\exposid{base_}, cref(*\exposid{pred_}))}.

\pnum
\remarks
In order to provide the amortized constant-time complexity
required by the \libconcept{range} concept
when \tcode{drop_while_view} models \libconcept{forward_range},
the first call caches the result within the \tcode{drop_while_view}
for use on subsequent calls.
\begin{note}
Without this,
applying a \tcode{reverse_view} over a \tcode{drop_while_view}
would have quadratic iteration complexity.
\end{note}
\end{itemdescr}

\rSec2[range.join]{Join view}

\rSec3[range.join.overview]{Overview}

\pnum
\tcode{join_view} flattens a view of ranges into a view.

\pnum
\indexlibrarymember{join}{views}%
The name \tcode{views::join} denotes a
range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E}, the expression
\tcode{views::join(E)} is expression-equivalent to
\tcode{join_view<views::all_t<decltype((E))>>\{E\}}.

\pnum
\begin{example}
\begin{codeblock}
vector<string> ss{"hello", " ", "world", "!"};
for (char ch : ss | views::join)
  cout << ch;                                   // prints \tcode{hello world!}
\end{codeblock}
\end{example}

\rSec3[range.join.view]{Class template \tcode{join_view}}

\indexlibraryglobal{join_view}%
\indexlibrarymember{base}{join_view}%
\indexlibrarymember{begin}{join_view}%
\indexlibrarymember{end}{join_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
  class join_view : public view_interface<join_view<V>> {
  private:
    using @\exposidnc{InnerRng}@ = range_reference_t<V>;                  // \expos

    // \ref{range.join.iterator}, class template \tcode{join_view::\exposid{iterator}}
    template<bool Const>
      struct @\exposidnc{iterator}@;                                      // \expos

    // \ref{range.join.sentinel}, class template \tcode{join_view::\exposid{sentinel}}
    template<bool Const>
      struct @\exposidnc{sentinel}@;                                      // \expos

    V @\exposid{base_}@ = V();                                          // \expos

    @\exposidnc{non-propagating-cache}@<iterator_t<V>> @\exposidnc{outer_}@;            // \expos, present only
                                                            // when \tcode{!\libconcept{forward_range}<V>}
    @\exposidnc{non-propagating-cache}@<remove_cv_t<@\exposidnc{InnerRng}@>> @\exposid{inner_}@;    // \expos, present only
                                                            // if \tcode{is_reference_v<\exposid{InnerRng}>} is \tcode{false}

  public:
    join_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit join_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() {
      if constexpr (@\libconcept{forward_range}@<V>) {
        constexpr bool use_const = @\exposconcept{simple-view}@<V> &&
                                   is_reference_v<@\exposid{InnerRng}@>;
        return @\exposid{iterator}@<use_const>{*this, ranges::begin(@\exposid{base_}@)};
      } else {
        @\exposid{outer_}@ = ranges::begin(@\exposid{base_}@);
        return @\exposid{iterator}@<false>{*this};
      }
    }

    constexpr auto begin() const
      requires @\libconcept{forward_range}@<const V> &&
               is_reference_v<range_reference_t<const V>> &&
               @\libconcept{input_range}@<range_reference_t<const V>>
    { return @\exposid{iterator}@<true>{*this, ranges::begin(@\exposid{base_}@)}; }

    constexpr auto end() {
      if constexpr (@\libconcept{forward_range}@<V> &&
                    is_reference_v<@\exposid{InnerRng}@> && @\libconcept{forward_range}@<@\exposid{InnerRng}@> &&
                    @\libconcept{common_range}@<V> && @\libconcept{common_range}@<@\exposid{InnerRng}@>)
        return @\exposid{iterator}@<@\exposconcept{simple-view}@<V>>{*this, ranges::end(@\exposid{base_}@)};
      else
        return @\exposid{sentinel}@<@\exposconcept{simple-view}@<V>>{*this};
    }

    constexpr auto end() const
      requires @\libconcept{forward_range}@<const V> &&
               is_reference_v<range_reference_t<const V>> &&
               @\libconcept{input_range}@<range_reference_t<const V>> {
      if constexpr (@\libconcept{forward_range}@<range_reference_t<const V>> &&
                    @\libconcept{common_range}@<const V> &&
                    @\libconcept{common_range}@<range_reference_t<const V>>)
        return @\exposid{iterator}@<true>{*this, ranges::end(@\exposid{base_}@)};
      else
        return @\exposid{sentinel}@<true>{*this};
    }
  };

  template<class R>
    explicit join_view(R&&) -> join_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{join_view}%
\begin{itemdecl}
constexpr explicit join_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec3[range.join.iterator]{Class template \tcode{join_view::\exposid{iterator}}}

\indexlibraryglobal{join_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
  template<bool Const>
  struct join_view<V>::@\exposid{iterator}@ {
  private:
    using @\exposidnc{Parent}@    = @\exposidnc{maybe-const}@<Const, join_view>;            // \expos
    using @\exposidnc{Base}@      = @\exposidnc{maybe-const}@<Const, V>;                    // \expos
    using @\exposidnc{OuterIter}@ = iterator_t<@\exposidnc{Base}@>;                         // \expos
    using @\exposidnc{InnerIter}@ = iterator_t<range_reference_t<@\exposidnc{Base}@>>;      // \expos

    static constexpr bool @\exposidnc{ref-is-glvalue}@ =                      // \expos
      is_reference_v<range_reference_t<@\exposidnc{Base}@>>;

    @\exposidnc{OuterIter}@ @\exposid{outer_}@ = @\exposidnc{OuterIter}@();                     // \expos, present only
                                                        // if \exposid{Base} models \libconcept{forward_range}
    optional<@\exposidnc{InnerIter}@> @\exposid{inner_}@;                                 // \expos
    @\exposidnc{Parent}@* @\exposid{parent_}@  = nullptr;                                 // \expos

    constexpr void @\exposidnc{satisfy}@();                                   // \expos

    constexpr @\exposidnc{OuterIter}@& @\exposidnc{outer}@();                               // \expos
    constexpr const @\exposidnc{OuterIter}@& @\exposidnc{outer}@() const;                   // \expos

    constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{OuterIter}@ outer)
      requires @\libconcept{forward_range}@<@\exposidnc{Base}@>;                             // \expos
    constexpr explicit @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent)
      requires (!@\libconcept{forward_range}@<@\exposidnc{Base}@>);                          // \expos

  public:
    using iterator_concept  = @\seebelow@;
    using iterator_category = @\seebelow@;                        // not always present
    using value_type        = range_value_t<range_reference_t<@\exposid{Base}@>>;
    using difference_type   = @\seebelow@;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const &&
               @\libconcept{convertible_to}@<iterator_t<V>, @\exposid{OuterIter}@> &&
               @\libconcept{convertible_to}@<iterator_t<@\exposid{InnerRng}@>, @\exposid{InnerIter}@>;

    constexpr decltype(auto) operator*() const { return **@\exposid{inner_}@; }

    constexpr @\exposid{InnerIter}@ operator->() const
      requires @\exposconcept{has-arrow}@<@\exposid{InnerIter}@> && @\libconcept{copyable}@<@\exposid{InnerIter}@>;

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int)
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> &&
               @\libconcept{forward_range}@<range_reference_t<@\exposid{Base}@>>;

    constexpr @\exposid{iterator}@& operator--()
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
               @\libconcept{bidirectional_range}@<range_reference_t<@\exposid{Base}@>> &&
               @\libconcept{common_range}@<range_reference_t<@\exposid{Base}@>>;

    constexpr @\exposid{iterator}@ operator--(int)
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
               @\libconcept{bidirectional_range}@<range_reference_t<@\exposid{Base}@>> &&
               @\libconcept{common_range}@<range_reference_t<@\exposid{Base}@>>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> &&
               @\libconcept{equality_comparable}@<iterator_t<range_reference_t<@\exposid{Base}@>>>;

    friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& i)
    noexcept(noexcept(ranges::iter_move(*i.@\exposid{inner_}@))) {
      return ranges::iter_move(*i.@\exposid{inner_}@);
    }

    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(*x.@\exposid{inner_}@, *y.@\exposid{inner_}@)))
      requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item If \exposid{ref-is-glvalue} is \tcode{true},
  \exposid{Base} models \libconcept{bidirectional_range}, and
  \tcode{range_reference_t<\exposid{Base}>} models
  both \libconcept{bidirectional_range} and \libconcept{common_range},
  then \tcode{iterator_concept} denotes \tcode{bidirectio\-nal_iterator_tag}.
\item Otherwise, if \exposid{ref-is-glvalue} is \tcode{true} and
  \exposid{Base} and \tcode{range_reference_t<\exposid{Base}>}
  each model \libconceptx{for\-ward_range}{forward_range}, then \tcode{iterator_concept} denotes
  \tcode{forward_iterator_tag}.
\item Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if \exposid{ref-is-glvalue} is \tcode{true},
\exposid{Base} models \libconcept{forward_range}, and
\tcode{range_reference_t<\exposid{Base}>} models \libconcept{forward_range}.
In that case,
\tcode{\exposid{iterator}::iter\-ator_category} is defined as follows:
\begin{itemize}
\item Let \placeholder{OUTERC} denote
  \tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}, and
  let \placeholder{INNERC} denote
  \tcode{iterator_traits<iterator_t<range_reference_t<\exposid{Base}>>>::iterator_category}.
\item If
  \placeholder{OUTERC} and \placeholder{INNERC} each model
  \tcode{\libconcept{derived_from}<bidirectional_iterator_tag>} and
  \tcode{range_reference_t<\exposid{Base}>} models \libconcept{common_range},
  \tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}.
\item Otherwise, if
  \placeholder{OUTERC} and \placeholder{INNERC} each model
  \tcode{\libconcept{derived_from}<forward_iterator_tag>}, \tcode{iter\-ator_category}
  denotes \tcode{forward_iterator_tag}.
\item Otherwise,
  \tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
\tcode{\exposid{iterator}::difference_type} denotes the type:
\begin{codeblock}
common_type_t<
  range_difference_t<@\exposid{Base}@>,
  range_difference_t<range_reference_t<@\exposid{Base}@>>>
\end{codeblock}

\pnum
\tcode{join_view} iterators use the \exposid{satisfy} function to skip over
empty inner ranges.

\indexlibrarymember{\exposid{outer}}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{OuterIter}@& @\exposid{outer}@();
constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{outer_} if \exposid{Base} models \libconcept{forward_range};
otherwise, \tcode{*\exposid{parent_}->\exposid{outer_}}.
\end{itemdescr}

\indexlibrarymember{\exposid{satisfy}}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void @\exposid{satisfy}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto update_inner = [this](const iterator_t<@\exposid{Base}@>& x) -> auto&& {
  if constexpr (@\exposid{ref-is-glvalue}@)     // \tcode{*x} is a reference
    return *x;
  else
    return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x);
};

for (; @\exposid{outer}@() != ranges::end(@\exposid{parent_}@->@\exposid{base_}@); ++@\exposid{outer}@()) {
  auto&& inner = update_inner(@\exposid{outer}@());
  @\exposid{inner_}@ = ranges::begin(inner);
  if (*@\exposid{inner_}@ != ranges::end(inner))
    return;
}
if constexpr (@\exposid{ref-is-glvalue}@)
  @\exposid{inner_}@.reset();
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer)
  requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{outer_} with \tcode{std::move(outer)} and
\exposid{parent_} with \tcode{addressof(parent)}; then calls \tcode{\exposid{satisfy}()}.
\end{itemdescr}

\indexlibraryctor{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(@\exposid{Parent}@& parent)
  requires (!@\libconcept{forward_range}@<@\exposid{Base}@>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)};
then calls \tcode{\exposid{satisfy}()}.
\end{itemdescr}

\indexlibraryctor{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const &&
           @\libconcept{convertible_to}@<iterator_t<V>, @\exposid{OuterIter}@> &&
           @\libconcept{convertible_to}@<iterator_t<@\exposid{InnerRng}@>, @\exposid{InnerIter}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{outer_} with \tcode{std::move(i.\exposid{outer_})},
\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}, and
\exposid{parent_} with \tcode{i.\exposid{parent_}}.

\pnum
\begin{note}
\tcode{Const} can only be \tcode{true}
when \exposid{Base} models \libconcept{forward_range}.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator->}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{InnerIter}@ operator->() const
  requires @\exposconcept{has-arrow}@<@\exposid{InnerIter}@> && @\libconcept{copyable}@<@\exposid{InnerIter}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{inner_};}
\end{itemdescr}

\indexlibrarymember{operator++}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{\placeholder{inner-range}} be:
\begin{itemize}
\item If \exposid{ref-is-glvalue} is \tcode{true}, \tcode{*\exposid{outer}()}.
\item Otherwise, \tcode{*\exposid{parent_}->\exposid{inner_}}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
if (++*@\exposid{inner_}@ == ranges::end(@\exposid{as-lvalue}@(@\placeholder{inner-range}@))) {
  ++@\exposid{outer}@();
  @\exposid{satisfy}@();
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int)
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> &&
           @\libconcept{forward_range}@<range_reference_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--()
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
           @\libconcept{bidirectional_range}@<range_reference_t<@\exposid{Base}@>> &&
           @\libconcept{common_range}@<range_reference_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if (@\exposid{outer_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@))
  @\exposid{inner_}@ = ranges::end(@\exposid{as-lvalue}@(*--@\exposid{outer_}@));
while (*@\exposid{inner_}@ == ranges::begin(@\exposid{as-lvalue}@(*@\exposid{outer_}@)))
  *@\exposid{inner_}@ = ranges::end(@\exposid{as-lvalue}@(*--@\exposid{outer_}@));
--*@\exposid{inner_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{join_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int)
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
           @\libconcept{bidirectional_range}@<range_reference_t<@\exposid{Base}@>> &&
           @\libconcept{common_range}@<range_reference_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{join_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> &&
           @\libconcept{equality_comparable}@<iterator_t<range_reference_t<@\exposid{Base}@>>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return x.\exposid{outer_} == y.\exposid{outer_} \&\& x.\exposid{inner_} == y.\exposid{inner_};}
\end{itemdescr}

\indexlibrarymember{iter_swap}{join_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(*x.@\exposid{inner_}@, *y.@\exposid{inner_}@)))
  requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{ranges::iter_swap(*x.\exposid{inner_}, *y.\exposid{inner_});}
\end{itemdescr}

\rSec3[range.join.sentinel]{Class template \tcode{join_view::\exposid{sentinel}}}

\indexlibraryglobal{join_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
  template<bool Const>
  struct join_view<V>::@\exposid{sentinel}@ {
  private:
    using @\exposid{Parent}@ = @\exposid{maybe-const}@<Const, join_view>;       // \expos
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                 // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();         // \expos
    constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent);        //  \expos

  public:
    @\exposid{sentinel}@() = default;

    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
  };
}
\end{codeblock}

\indexlibraryctor{join_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}.
\end{itemdescr}

\indexlibraryctor{join_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{join_view::\exposid{sentinel}}%3431
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{outer}() == y.\exposid{end_};}
\end{itemdescr}

\rSec2[range.join.with]{Join with view}

\rSec3[range.join.with.overview]{Overview}

\pnum
\tcode{join_with_view} takes a view and a delimiter, and
flattens the view,
inserting every element of the delimiter
in between elements of the view.
The delimiter can be a single element or a view of elements.

\pnum
\indexlibrarymember{join_with}{views}%
The name \tcode{views::join_with} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expression \tcode{views::join_with(E, F)} is expression-equivalent to
\tcode{join_with_view(E, F)}.

\pnum
\begin{example}
\begin{codeblock}
vector<string> vs = {"the", "quick", "brown", "fox"};
for (char c : vs | views::join_with('-')) {
  cout << c;
}
// The above prints \tcode{the-quick-brown-fox}
\end{codeblock}
\end{example}

\rSec3[range.join.with.view]{Class template \tcode{join_with_view}}

\indexlibraryglobal{join_with_view}%
\begin{codeblock}
namespace std::ranges {
  template<class R>
  concept @\defexposconcept{bidirectional-common}@ = @\libconcept{bidirectional_range}@<R> && @\libconcept{common_range}@<R>;    // \expos

  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
          && @\libconcept{view}@<Pattern>
          && @\exposconcept{concatable}@<range_reference_t<V>, Pattern>
  class join_with_view : public view_interface<join_with_view<V, Pattern>> {
    using @\exposid{InnerRng}@ = range_reference_t<V>;                  // \expos

    V @\exposid{base_}@ = V();                                          // \expos
    @\exposid{non-propagating-cache}@<iterator_t<V>> @\exposid{outer_it_}@;         // \expos, present only
                                                            // when \tcode{!\libconcept{forward_range}<V>}
    @\exposid{non-propagating-cache}@<remove_cv_t<@\exposid{InnerRng}@>> @\exposid{inner_}@;   // \expos, present only
                                                            // if \tcode{is_reference_v<\exposid{InnerRng}>} is \tcode{false}
    Pattern @\exposid{pattern_}@ = Pattern();                           // \expos

    // \ref{range.join.with.iterator}, class template \tcode{join_with_view::\exposid{iterator}}
    template<bool Const> struct @\exposid{iterator}@;                   // \expos

    // \ref{range.join.with.sentinel}, class template \tcode{join_with_view::\exposid{sentinel}}
    template<bool Const> struct @\exposid{sentinel}@;                   // \expos

  public:
    join_with_view()
      requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pattern> = default;

    constexpr explicit join_with_view(V base, Pattern pattern);

    template<@\libconcept{input_range}@ R>
      requires @\libconcept{constructible_from}@<V, views::all_t<R>> &&
               @\libconcept{constructible_from}@<Pattern, single_view<range_value_t<@\exposid{InnerRng}@>>>
    constexpr explicit join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() {
      if constexpr (@\libconcept{forward_range}@<V>) {
        constexpr bool use_const =
          @\exposconcept{simple-view}@<V> && is_reference_v<@\exposid{InnerRng}@> && @\exposconcept{simple-view}@<Pattern>;
        return @\exposid{iterator}@<use_const>{*this, ranges::begin(@\exposid{base_}@)};
      }
      else {
        @\exposid{outer_it_}@ = ranges::begin(@\exposid{base_}@);
        return @\exposid{iterator}@<false>{*this};
      }
    }
    constexpr auto begin() const
      requires @\libconcept{forward_range}@<const V> &&
               @\libconcept{forward_range}@<const Pattern> &&
               is_reference_v<range_reference_t<const V>> &&
               @\libconcept{input_range}@<range_reference_t<const V>> &&
               @\exposconcept{concatable}@<range_reference_t<const V>, const Pattern> {
      return @\exposid{iterator}@<true>{*this, ranges::begin(@\exposid{base_}@)};
    }

    constexpr auto end() {
      if constexpr (@\libconcept{forward_range}@<V> &&
                    is_reference_v<@\exposid{InnerRng}@> && @\libconcept{forward_range}@<@\exposid{InnerRng}@> &&
                    @\libconcept{common_range}@<V> && @\libconcept{common_range}@<@\exposid{InnerRng}@>)
        return @\exposid{iterator}@<@\exposconcept{simple-view}@<V> && @\exposconcept{simple-view}@<Pattern>>{*this, ranges::end(@\exposid{base_}@)};
      else
        return @\exposid{sentinel}@<@\exposconcept{simple-view}@<V> && @\exposconcept{simple-view}@<Pattern>>{*this};
    }
    constexpr auto end() const
      requires @\libconcept{forward_range}@<const V> && @\libconcept{forward_range}@<const Pattern> &&
               is_reference_v<range_reference_t<const V>> &&
               @\libconcept{input_range}@<range_reference_t<const V>> &&
               @\exposconcept{concatable}@<range_reference_t<const V>, const Pattern> {
      using InnerConstRng = range_reference_t<const V>;
      if constexpr (@\libconcept{forward_range}@<InnerConstRng> &&
                    @\libconcept{common_range}@<const V> && @\libconcept{common_range}@<InnerConstRng>)
        return @\exposid{iterator}@<true>{*this, ranges::end(@\exposid{base_}@)};
      else
        return @\exposid{sentinel}@<true>{*this};
    }
  };

  template<class R, class P>
    join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>;

  template<@\libconcept{input_range}@ R>
    join_with_view(R&&, range_value_t<range_reference_t<R>>)
      -> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>;
}
\end{codeblock}

\indexlibraryctor{join_with_view}%
\begin{itemdecl}
constexpr explicit join_with_view(V base, Pattern pattern);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{pattern_} with \tcode{std::move(pattern)}.
\end{itemdescr}

\indexlibraryctor{join_with_view}%
\begin{itemdecl}
template<@\libconcept{input_range}@ R>
  requires @\libconcept{constructible_from}@<V, views::all_t<R>> &&
           @\libconcept{constructible_from}@<Pattern, single_view<range_value_t<@\exposid{InnerRng}@>>>
constexpr explicit join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{views::all(std::forward<R>(r))} and
\exposid{pattern_} with \tcode{views::sin\-gle(std::move(e))}.
\end{itemdescr}

\rSec3[range.join.with.iterator]{Class template \tcode{join_with_view::\exposid{iterator}}}

\indexlibraryglobal{join_with_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
          && @\libconcept{view}@<Pattern> && @\exposconcept{concatable}@<range_reference_t<V>, Pattern>
  template<bool Const>
  class join_with_view<V, Pattern>::@\exposid{iterator}@ {
    using @\exposid{Parent}@ = @\exposid{maybe-const}@<Const, join_with_view>;                  // \expos
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                                 // \expos
    using @\exposid{InnerBase}@ = range_reference_t<@\exposid{Base}@>;                          // \expos
    using @\exposid{PatternBase}@ = @\exposid{maybe-const}@<Const, Pattern>;                    // \expos

    using @\exposid{OuterIter}@ = iterator_t<@\exposid{Base}@>;                                 // \expos
    using @\exposid{InnerIter}@ = iterator_t<@\exposid{InnerBase}@>;                            // \expos
    using @\exposid{PatternIter}@ = iterator_t<@\exposid{PatternBase}@>;                        // \expos

    static constexpr bool @\exposid{ref-is-glvalue}@ = is_reference_v<@\exposid{InnerBase}@>;   // \expos

    @\exposid{Parent}@* @\exposid{parent_}@ = nullptr;                                          // \expos
    @\exposid{OuterIter}@ @\exposid{outer_it_}@ = @\exposid{OuterIter}@();                          // \expos, present only
                                                                // if \exposid{Base} models \libconcept{forward_range}
    variant<@\exposid{PatternIter}@, @\exposid{InnerIter}@> @\exposid{inner_it_}@;                          // \expos

    constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer)
      requires @\libconcept{forward_range}@<@\exposid{Base}@>;                                     // \expos
    constexpr explicit @\exposid{iterator}@(@\exposid{Parent}@& parent)
      requires (!@\libconcept{forward_range}@<@\exposid{Base}@>);                                  // \expos
    constexpr @\exposid{OuterIter}@& @\exposid{outer}@();                                       // \expos
    constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const;                           // \expos
    constexpr auto& @\exposid{update-inner}@();                                     // \expos
    constexpr auto& @\exposid{get-inner}@();                                        // \expos
    constexpr void @\exposid{satisfy}@();                                           // \expos

  public:
    using iterator_concept = @\seebelow@;
    using iterator_category = @\seebelow@;                                // not always present
    using value_type = @\seebelow@;
    using difference_type = @\seebelow@;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, @\exposid{OuterIter}@> &&
               @\libconcept{convertible_to}@<iterator_t<@\exposid{InnerRng}@>, @\exposid{InnerIter}@> &&
               @\libconcept{convertible_to}@<iterator_t<Pattern>, @\exposid{PatternIter}@>;

    constexpr decltype(auto) operator*() const;

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int)
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> &&
               @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>;

    constexpr @\exposid{iterator}@& operator--()
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
               @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>;
    constexpr @\exposid{iterator}@ operator--(int)
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
               @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> &&
               @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>;

    friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& x) {
      using rvalue_reference = common_reference_t<
        iter_rvalue_reference_t<@\exposid{InnerIter}@>,
        iter_rvalue_reference_t<@\exposid{PatternIter}@>>;
      return visit<rvalue_reference>(ranges::iter_move, x.@\exposid{inner_it_}@);
    }

    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@, @\exposid{PatternIter}@> {
      visit(ranges::iter_swap, x.@\exposid{inner_it_}@, y.@\exposid{inner_it_}@);
    }
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \exposid{ref-is-glvalue} is \tcode{true},
\exposid{Base} models \libconcept{bidirectional_range}, and
\exposid{InnerBase} and \exposid{PatternBase}
each model \exposconcept{bidirectional-common},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, if \exposid{ref-is-glvalue} is \tcode{true} and
\exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range},
then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if \exposid{ref-is-glvalue} is \tcode{true}, and
\exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range}.
In that case,
\tcode{\exposid{iterator}::iterator_category} is defined as follows:

\begin{itemize}
\item
Let \placeholder{OUTERC} denote
\tcode{iterator_traits<\exposid{OuterIter}>::iterator_category},
let \placeholder{INNERC} denote
\tcode{iterator_traits<\exposid{InnerIter}>::iterator_category}, and
let \placeholder{PATTERNC} denote
\tcode{iterator_-\linebreak traits<\exposid{PatternIter}>::iterator_category}.
\item
If
\begin{codeblock}
is_reference_v<common_reference_t<iter_reference_t<@\exposid{InnerIter}@>,
                                  iter_reference_t<@\exposid{PatternIter}@>>>
\end{codeblock}
is \tcode{false},
\tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\item
Otherwise,
if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC}
each model \tcode{\libconcept{derived_from}<bidirectional_iterator_tag>}
and \exposid{InnerBase} and \exposid{PatternBase}
each model \libconcept{common_range},
\tcode{iterator_cate\-gory} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise,
if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC}
each model \tcode{\libconcept{derived_from}<forward_iterator_tag>},
\tcode{iterator_category} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
\tcode{\exposid{iterator}::value_type} denotes the type:
\begin{codeblock}
common_type_t<iter_value_t<@\exposid{InnerIter}@>, iter_value_t<@\exposid{PatternIter}@>>
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::difference_type} denotes the type:
\begin{codeblock}
common_type_t<
  iter_difference_t<@\exposid{OuterIter}@>,
  iter_difference_t<@\exposid{InnerIter}@>,
  iter_difference_t<@\exposid{PatternIter}@>>
\end{codeblock}

\indexlibrarymember{\exposid{outer}}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{OuterIter}@& @\exposid{outer}@();
constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{outer_it_} if \exposid{Base} models \libconcept{forward_range};
otherwise, \tcode{*\exposid{parent_}->\exposid{outer_it_}}.
\end{itemdescr}

\indexlibrarymember{\exposid{update-inner}}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto& @\exposid{update-inner}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\exposid{ref-is-glvalue}@)
  return @\exposid{as-lvalue}@(*@\exposid{outer}@());
else
  return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(@\exposid{outer}@());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{get-inner}}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto& @\exposid{get-inner}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\exposid{ref-is-glvalue}@)
  return @\exposid{as-lvalue}@(*@\exposid{outer}@());
else
  return *@\exposid{parent_}@->@\exposid{inner_}@;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{satisfy}}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void @\exposid{satisfy}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
while (true) {
  if (@\exposid{inner_it_}@.index() == 0) {
    if (std::get<0>(@\exposid{inner_it_}@) != ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@))
      break;
    @\exposid{inner_it_}@.template emplace<1>(ranges::begin(@\exposid{update-inner}@()));
  } else {
    if (std::get<1>(@\exposid{inner_it_}@) != ranges::end(@\exposid{get-inner}@()))
      break;
    if (++@\exposid{outer}@() == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) {
      if constexpr (@\exposid{ref-is-glvalue}@)
        @\exposid{inner_it_}@.template emplace<0>();
      break;
    }
    @\exposid{inner_it_}@.template emplace<0>(ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@));
  }
}
\end{codeblock}

\begin{note}
\tcode{join_with_view} iterators use the \exposid{satisfy} function
to skip over empty inner ranges.
\end{note}
\end{itemdescr}

\indexlibraryctor{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer)
  requires @\libconcept{forward_range}@<@\exposid{Base}@>;
constexpr explicit @\exposid{iterator}@(@\exposid{Parent}@& parent)
  requires (!@\libconcept{forward_range}@<@\exposid{Base}@>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}.
For the first overload, also initializes
\exposid{outer_it_} with \tcode{std::move(outer)}.
Then, equivalent to:
\begin{codeblock}
if (@\exposid{outer}@() != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) {
  @\exposid{inner_it_}@.template emplace<1>(ranges::begin(@\exposid{update-inner}@()));
  @\exposidnc{satisfy}@();
}
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
    requires Const && @\libconcept{convertible_to}@<iterator_t<V>, @\exposid{OuterIter}@> &&
             @\libconcept{convertible_to}@<iterator_t<@\exposid{InnerRng}@>, @\exposid{InnerIter}@> &&
             @\libconcept{convertible_to}@<iterator_t<Pattern>, @\exposid{PatternIter}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{outer_it_} with
\tcode{std::move(i.\exposid{outer_it_})} and
\exposid{parent_} with \tcode{i.\exposid{parent_}}.
Then, equivalent to:
\begin{codeblock}
if (i.@\exposid{inner_it_}@.index() == 0)
  @\exposid{inner_it_}@.template emplace<0>(std::get<0>(std::move(i.@\exposid{inner_it_}@)));
else
  @\exposid{inner_it_}@.template emplace<1>(std::get<1>(std::move(i.@\exposid{inner_it_}@)));
\end{codeblock}

\pnum
\begin{note}
\tcode{Const} can only be \tcode{true}
when \exposid{Base} models \libconcept{forward_range}.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
using reference =
  common_reference_t<iter_reference_t<@\exposid{InnerIter}@>, iter_reference_t<@\exposid{PatternIter}@>>;
return visit([](auto& it) -> reference { return *it; }, @\exposid{inner_it_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
visit([](auto& it){ ++it; }, @\exposid{inner_it_}@);
@\exposidnc{satisfy}@();
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int)
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{iterator}@ tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--()
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
           @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if (@\exposid{outer_it_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) {
  auto&& inner = *--@\exposid{outer_it_}@;
  @\exposid{inner_it_}@.template emplace<1>(ranges::end(inner));
}

while (true) {
  if (@\exposid{inner_it_}@.index() == 0) {
    auto& it = std::get<0>(@\exposid{inner_it_}@);
    if (it == ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)) {
      auto&& inner = *--@\exposid{outer_it_}@;
      @\exposid{inner_it_}@.template emplace<1>(ranges::end(inner));
    } else {
      break;
    }
  } else {
    auto& it = std::get<1>(@\exposid{inner_it_}@);
    auto&& inner = *@\exposid{outer_it_}@;
    if (it == ranges::begin(inner)) {
      @\exposid{inner_it_}@.template emplace<0>(ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@));
    } else {
      break;
    }
  }
}
visit([](auto& it){ --it; }, @\exposid{inner_it_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int)
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> &&
           @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{iterator}@ tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{join_with_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> &&
           @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.@\exposid{outer_it_}@ == y.@\exposid{outer_it_}@ && x.@\exposid{inner_it_}@ == y.@\exposid{inner_it_}@;
\end{codeblock}
\end{itemdescr}

\rSec3[range.join.with.sentinel]{Class template \tcode{join_with_view::\exposid{sentinel}}}

\indexlibraryglobal{join_with_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
          && @\libconcept{view}@<Pattern> && @\exposconcept{concatable}@<range_reference_t<V>, Pattern>
  template<bool Const>
  class join_with_view<V, Pattern>::@\exposid{sentinel}@ {
    using @\exposid{Parent}@ = @\exposid{maybe-const}@<Const, join_with_view>;  // \expos
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                 // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();         // \expos

    constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent);        // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
  };
}
\end{codeblock}

\indexlibraryctor{join_with_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}.
\end{itemdescr}

\indexlibraryctor{join_with_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> s)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{join_with_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{outer}() == y.\exposid{end_};}
\end{itemdescr}

\rSec2[range.lazy.split]{Lazy split view}

\rSec3[range.lazy.split.overview]{Overview}

\pnum
\tcode{lazy_split_view} takes a view and a delimiter, and splits
the view into subranges on the delimiter. The delimiter can be
a single element or a view of elements.

\pnum
\indexlibrarymember{lazy_split}{views}%
The name \tcode{views::lazy_split} denotes a
range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expression \tcode{views::lazy_split(E, F)} is expression-equivalent to
\tcode{lazy_split_view(E, F)}.

\pnum
\begin{example}
\begin{codeblock}
string str{"the quick brown fox"};
for (auto word : str | views::lazy_split(' ')) {
  for (char ch : word)
    cout << ch;
  cout << '*';
}
// The above prints \tcode{the*quick*brown*fox*}
\end{codeblock}
\end{example}

\rSec3[range.lazy.split.view]{Class template \tcode{lazy_split_view}}

\indexlibraryglobal{lazy_split_view}%
\indexlibrarymember{base}{lazy_split_view}%
\indexlibrarymember{begin}{lazy_split_view}%
\indexlibrarymember{end}{lazy_split_view}%
\begin{codeblock}
namespace std::ranges {
  template<auto> struct @\exposidnc{require-constant}@;                       // \expos

  template<class R>
  concept @\defexposconceptnc{tiny-range}@ =                                          // \expos
    @\libconcept{sized_range}@<R> &&
    requires { typename @\exposid{require-constant}@<remove_reference_t<R>::size()>; } &&
    (remove_reference_t<R>::size() <= 1);

  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (@\libconcept{forward_range}@<V> || @\exposconcept{tiny-range}@<Pattern>)
  class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {
  private:
    V @\exposid{base_}@ = V();                                              // \expos
    Pattern @\exposid{pattern_}@ = Pattern();                               // \expos

    @\exposidnc{non-propagating-cache}@<iterator_t<V>> @\exposid{current_}@;              // \expos, present only
                                                                // if \tcode{\libconcept{forward_range}<V>} is \tcode{false}

    // \ref{range.lazy.split.outer}, class template \tcode{lazy_split_view::\exposid{outer-iterator}}
    template<bool> struct @\exposidnc{outer-iterator}@;                       // \expos

    // \ref{range.lazy.split.inner}, class template \tcode{lazy_split_view::\exposid{inner-iterator}}
    template<bool> struct @\exposidnc{inner-iterator}@;                       // \expos

  public:
    lazy_split_view()
      requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pattern> = default;
    constexpr explicit lazy_split_view(V base, Pattern pattern);

    template<@\libconcept{input_range}@ R>
      requires @\libconcept{constructible_from}@<V, views::all_t<R>> &&
               @\libconcept{constructible_from}@<Pattern, single_view<range_value_t<R>>>
    constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() {
      if constexpr (@\libconcept{forward_range}@<V>) {
        return @\exposid{outer-iterator}@<@\exposconcept{simple-view}@<V> && @\exposconcept{simple-view}@<Pattern>>
          {*this, ranges::begin(@\exposid{base_}@)};
      } else {
        @\exposid{current_}@ = ranges::begin(@\exposid{base_}@);
        return @\exposid{outer-iterator}@<false>{*this};
      }
    }

    constexpr auto begin() const requires @\libconcept{forward_range}@<V> && @\libconcept{forward_range}@<const V> &&
                                          @\libconcept{forward_range}@<const Pattern> {
      return @\exposid{outer-iterator}@<true>{*this, ranges::begin(@\exposid{base_}@)};
    }

    constexpr auto end() requires @\libconcept{forward_range}@<V> && @\libconcept{common_range}@<V> {
      return @\exposid{outer-iterator}@<@\exposconcept{simple-view}@<V> && @\exposconcept{simple-view}@<Pattern>>
        {*this, ranges::end(@\exposid{base_}@)};
    }

    constexpr auto end() const {
      if constexpr (@\libconcept{forward_range}@<V> && @\libconcept{forward_range}@<const V> && @\libconcept{common_range}@<const V> &&
                    @\libconcept{forward_range}@<const Pattern>)
        return @\exposid{outer-iterator}@<true>{*this, ranges::end(@\exposid{base_}@)};
      else
        return default_sentinel;
    }
  };

  template<class R, class P>
    lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>;

  template<@\libconcept{input_range}@ R>
    lazy_split_view(R&&, range_value_t<R>)
      -> lazy_split_view<views::all_t<R>, single_view<range_value_t<R>>>;
}
\end{codeblock}

\indexlibraryctor{lazy_split_view}%
\begin{itemdecl}
constexpr explicit lazy_split_view(V base, Pattern pattern);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}, and
\exposid{pattern_} with \tcode{std::move(pattern)}.
\end{itemdescr}

\indexlibraryctor{lazy_split_view}%
\begin{itemdecl}
template<@\libconcept{input_range}@ R>
  requires @\libconcept{constructible_from}@<V, views::all_t<R>> &&
           @\libconcept{constructible_from}@<Pattern, single_view<range_value_t<R>>>
constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{views::all(std::forward<R>(r))}, and
\exposid{pattern_} with \tcode{views::\linebreak single(std::move(e))}.
\end{itemdescr}

\rSec3[range.lazy.split.outer]{Class template \tcode{lazy_split_view::\exposid{outer-iterator}}}

\indexlibraryglobal{lazy_split_view::\exposid{outer-iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (@\libconcept{forward_range}@<V> || @\exposconcept{tiny-range}@<Pattern>)
  template<bool Const>
  struct lazy_split_view<V, Pattern>::@\exposid{outer-iterator}@ {
  private:
    using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@<Const, lazy_split_view>;     // \expos
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                     // \expos
    @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr;                              // \expos

    iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>();         // \expos, present only
                                                            // if \tcode{V} models \libconcept{forward_range}

    bool @\exposid{trailing_empty_}@ = false;                           // \expos
    constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent)      // \expos
      requires (!@\libconcept{forward_range}@<@\exposid{Base}@>);
    constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current)    // \expos
      requires @\libconcept{forward_range}@<@\exposid{Base}@>;

  public:
    using iterator_concept  =
      conditional_t<@\libconcept{forward_range}@<@\exposid{Base}@>, forward_iterator_tag, input_iterator_tag>;

    using iterator_category = input_iterator_tag;           // present only if \exposid{Base}
                                                            // models \libconcept{forward_range}

    // \ref{range.lazy.split.outer.value}, class \tcode{lazy_split_view::\exposid{outer-iterator}::value_type}
    struct value_type;
    using difference_type   = range_difference_t<@\exposid{Base}@>;

    @\exposid{outer-iterator}@() = default;
    constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr value_type operator*() const;

    constexpr @\exposid{outer-iterator}@& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (@\libconcept{forward_range}@<@\exposid{Base}@>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }

    friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, const @\exposid{outer-iterator}@& y)
      requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t);
  };
}
\end{codeblock}

\pnum
Many of the specifications in \ref{range.lazy.split} refer to the notional member
\placeholder{current} of \exposid{outer-iterator}.
\placeholder{current} is equivalent to \exposid{current_} if \tcode{V}
models \libconcept{forward_range}, and \tcode{*\exposid{parent_}->\exposid{current_}} otherwise.

\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent)
  requires (!@\libconcept{forward_range}@<@\exposid{Base}@>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current)
  requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}
and \exposid{current_} with \tcode{std::move(current)}.
\end{itemdescr}

\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}},
\exposid{current_} with \tcode{std::move(i.\exposid{current_})}, and
\exposid{trailing_empty_} with \tcode{i.\exposid{trailing_empty_}}.
\end{itemdescr}

\indexlibrarymember{operator*}{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr value_type operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return value_type\{*this\};}
\end{itemdescr}

\indexlibrarymember{operator++}{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr @\exposid{outer-iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
const auto end = ranges::end(@\exposid{parent_}@->@\exposid{base_}@);
if (@\placeholder{current}@ == end) {
  @\exposid{trailing_empty_}@ = false;
  return *this;
}
const auto [pbegin, pend] = subrange{@\exposid{parent_}@->@\exposid{pattern_}@};
if (pbegin == pend) ++@\placeholder{current}@;
else if constexpr (@\exposconcept{tiny-range}@<Pattern>) {
  @\placeholder{current}@ = ranges::find(std::move(@\placeholder{current}@), end, *pbegin);
  if (@\placeholder{current}@ != end) {
    ++@\placeholder{current}@;
    if (@\placeholder{current}@ == end)
      @\exposid{trailing_empty_}@ = true;
  }
}
else {
  do {
    auto [b, p] = ranges::mismatch(@\placeholder{current}@, end, pbegin, pend);
    if (p == pend) {
      @\placeholder{current}@ = b;
      if (@\placeholder{current}@ == end)
        @\exposid{trailing_empty_}@ = true;
      break;            // The pattern matched; skip it
    }
  } while (++@\placeholder{current}@ != end);
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, const @\exposid{outer-iterator}@& y)
  requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.@\exposid{current_}@ == y.@\exposid{current_}@ && x.@\exposid{trailing_empty_}@ == y.@\exposid{trailing_empty_}@;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{lazy_split_view::\exposid{outer-iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.@\placeholdernc{current}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && !x.@\exposid{trailing_empty_}@;
\end{codeblock}
\end{itemdescr}

\rSec3[range.lazy.split.outer.value]{Class \tcode{lazy_split_view::\exposid{outer-iterator}::value_type}}

\indexlibraryglobal{lazy_split_view::\exposid{outer-iterator}::value_type}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (@\libconcept{forward_range}@<V> || @\exposconcept{tiny-range}@<Pattern>)
  template<bool Const>
  struct lazy_split_view<V, Pattern>::@\exposid{outer-iterator}@<Const>::value_type
    : view_interface<value_type> {
  private:
    @\exposid{outer-iterator}@ @\exposid{i_}@ = @\exposid{outer-iterator}@();               // \expos

    constexpr explicit value_type(@\exposid{outer-iterator}@ i);    // \expos

  public:
    constexpr @\exposid{inner-iterator}@<Const> begin() const;
    constexpr default_sentinel_t end() const noexcept;
  };
}
\end{codeblock}

\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr explicit value_type(@\exposid{outer-iterator}@ i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{i_} with \tcode{std::move(i)}.
\end{itemdescr}

\indexlibrarymember{begin}{lazy_split_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr @\exposid{inner-iterator}@<Const> begin() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{inner-iterator}<Const>\{\exposid{i_}\};}
\end{itemdescr}

\indexlibrarymember{end}{lazy_split_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr default_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return default_sentinel;}
\end{itemdescr}

\rSec3[range.lazy.split.inner]{Class template \tcode{lazy_split_view::\exposid{inner-iterator}}}

\indexlibraryglobal{lazy_split_view::\exposid{inner-iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (@\libconcept{forward_range}@<V> || @\exposconcept{tiny-range}@<Pattern>)
  template<bool Const>
  struct lazy_split_view<V, Pattern>::@\exposid{inner-iterator}@ {
  private:
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                             // \expos
    @\exposidnc{outer-iterator}@<Const> @\exposid{i_}@ = @\exposidnc{outer-iterator}@<Const>();             // \expos
    bool @\exposid{incremented_}@ = false;                                      // \expos
    constexpr explicit @\exposid{inner-iterator}@(@\exposidnc{outer-iterator}@<Const> i);     // \expos

  public:
    using iterator_concept  = @\exposid{outer-iterator}@<Const>::iterator_concept;

    using iterator_category = @\seebelownc@;                    // present only if \exposid{Base}
                                                            // models \libconcept{forward_range}
    using value_type        = range_value_t<@\exposid{Base}@>;
    using difference_type   = range_difference_t<@\exposid{Base}@>;

    @\exposid{inner-iterator}@() = default;

    constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
    constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@<V>;

    constexpr decltype(auto) operator*() const { return *@\exposid{i_}@.@\placeholder{current}@; }

    constexpr @\exposid{inner-iterator}@& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (@\libconcept{forward_range}@<@\exposid{Base}@>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }

    friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y)
      requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t);

    friend constexpr decltype(auto) iter_move(const @\exposid{inner-iterator}@& i)
    noexcept(noexcept(ranges::iter_move(i.@\exposid{i_}@.@\placeholdernc{current}@))) {
      return ranges::iter_move(i.@\exposid{i_}@.@\placeholdernc{current}@);
    }

    friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(x.@\exposid{i_}@.@\placeholdernc{current}@, y.@\exposid{i_}@.@\placeholdernc{current}@)))
      requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
If \exposid{Base} does not model \libconcept{forward_range}
there is no member \tcode{iterator_category}.
Otherwise, the \grammarterm{typedef-name} \tcode{iterator_category} denotes:
\begin{itemize}
\item
\tcode{forward_iterator_tag} if
\tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category} models \linebreak
\tcode{\libconcept{derived_from}<forward_iterator_tag>};
\item otherwise, \tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}.
\end{itemize}

\indexlibraryctor{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{inner-iterator}@(@\exposid{outer-iterator}@<Const> i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{i_} with \tcode{std::move(i)}.
\end{itemdescr}

\indexlibrarymember{base}{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{i_}.\placeholder{current};}
\end{itemdescr}

\indexlibrarymember{base}{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@<V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return std::move(\exposid{i_}.\placeholder{current});}
\end{itemdescr}

\indexlibrarymember{operator++}{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr @\exposid{inner-iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{incremented_}@ = true;
if constexpr (!@\libconcept{forward_range}@<@\exposid{Base}@>) {
  if constexpr (Pattern::size() == 0) {
    return *this;
  }
}
++@\exposid{i_}@.@\placeholder{current}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y)
  requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{i_}.\placeholder{current} == y.\exposid{i_}.\placeholder{current};}
\end{itemdescr}

\indexlibrarymember{operator==}{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto [pcur, pend] = subrange{x.@\exposid{i_}@.@\exposid{parent_}@->@\exposid{pattern_}@};
auto end = ranges::end(x.@\exposid{i_}@.@\exposid{parent_}@->@\exposid{base_}@);
if constexpr (@\exposconcept{tiny-range}@<Pattern>) {
  const auto & cur = x.@\exposid{i_}@.@\placeholder{current}@;
  if (cur == end) return true;
  if (pcur == pend) return x.@\exposid{incremented_}@;
  return *cur == *pcur;
} else {
  auto cur = x.@\exposid{i_}@.@\placeholder{current}@;
  if (cur == end) return true;
  if (pcur == pend) return x.@\exposid{incremented_}@;
  do {
    if (*cur != *pcur) return false;
    if (++pcur == pend) return true;
  } while (++cur != end);
  return false;
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{iter_swap}{lazy_split_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(x.@\exposid{i_}@.@\placeholdernc{current}@, y.@\exposid{i_}@.@\placeholdernc{current}@)))
  requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to
\tcode{ranges::iter_swap(x.\exposid{i_}.\placeholdernc{current}, y.\exposid{i_}.\placeholdernc{current})}.
\end{itemdescr}

\rSec2[range.split]{Split view}

\rSec3[range.split.overview]{Overview}

\pnum
\tcode{split_view} takes a view and a delimiter, and
splits the view into \tcode{subrange}s on the delimiter.
The delimiter can be a single element or a view of elements.

\pnum
The name \tcode{views::split} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expression \tcode{views::split(E, F)} is expression-equivalent to
\tcode{split_view(E, F)}.

\pnum
\begin{example}
\begin{codeblock}
string str{"the quick brown fox"};
for (auto word : views::split(str, ' ')) {
  cout << string_view(word) << '*';
}
// The above prints \tcode{the*quick*brown*fox*}
\end{codeblock}
\end{example}

\rSec3[range.split.view]{Class template \tcode{split_view}}

\indexlibraryglobal{split_view}
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  class split_view : public view_interface<split_view<V, Pattern>> {
  private:
    V @\exposid{base_}@ = V();                              // \expos
    Pattern @\exposid{pattern_}@ = Pattern();               // \expos

    // \ref{range.split.iterator}, class \tcode{split_view::\exposid{iterator}}
    struct @\exposid{iterator}@;                            // \expos

    // \ref{range.split.sentinel}, class \tcode{split_view::\exposid{sentinel}}
    struct @\exposid{sentinel}@;                            // \expos

  public:
    split_view()
      requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pattern> = default;
    constexpr explicit split_view(V base, Pattern pattern);

    template<@\libconcept{forward_range}@ R>
      requires @\libconcept{constructible_from}@<V, views::all_t<R>> &&
               @\libconcept{constructible_from}@<Pattern, single_view<range_value_t<R>>>
    constexpr explicit split_view(R&& r, range_value_t<R> e);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr @\exposid{iterator}@ begin();

    constexpr auto end() {
      if constexpr (@\libconcept{common_range}@<V>) {
        return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@), {}};
      } else {
        return @\exposid{sentinel}@{*this};
      }
    }

    constexpr subrange<iterator_t<V>> @\exposid{find-next}@(iterator_t<V>); // \expos
  };

  template<class R, class P>
    split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;

  template<@\libconcept{forward_range}@ R>
    split_view(R&&, range_value_t<R>)
      -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
}
\end{codeblock}

\indexlibraryctor{split_view}
\begin{itemdecl}
constexpr explicit split_view(V base, Pattern pattern);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}, and
\exposid{pattern_} with \tcode{std::move(pattern)}.
\end{itemdescr}

\indexlibraryctor{split_view}%
\begin{itemdecl}
template<@\libconcept{forward_range}@ R>
  requires @\libconcept{constructible_from}@<V, views::all_t<R>> &&
           @\libconcept{constructible_from}@<Pattern, single_view<range_value_t<R>>>
constexpr explicit split_view(R&& r, range_value_t<R> e);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{views::all(std::forward<R>(r))}, and
\exposid{pattern_} with \tcode{views::\linebreak single(std::move(e))}.
\end{itemdescr}

\indexlibrarymember{begin}{split_view}
\begin{itemdecl}
constexpr @\exposid{iterator}@ begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\{*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_}))\}}.

\pnum
\remarks
In order to provide the amortized constant time complexity
required by the \libconcept{range} concept,
this function caches the result within the \tcode{split_view}
for use on subsequent calls.
\end{itemdescr}

\indexlibrarymember{\exposid{find-next}}{split_view}
\begin{itemdecl}
constexpr subrange<iterator_t<V>> @\exposid{find-next}@(iterator_t<V> it);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto [b, e] = ranges::search(subrange(it, ranges::end(@\exposid{base_}@)), @\exposid{pattern_}@);
if (b != ranges::end(@\exposid{base_}@) && ranges::empty(@\exposid{pattern_}@)) {
  ++b;
  ++e;
}
return {b, e};
\end{codeblock}
\end{itemdescr}

\rSec3[range.split.iterator]{Class \tcode{split_view::\exposid{iterator}}}

\indexlibraryglobal{split_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  class split_view<V, Pattern>::@\exposid{iterator}@ {
  private:
    split_view* @\exposid{parent_}@ = nullptr;                                      // \expos
    iterator_t<V> @\exposid{cur_}@ = iterator_t<V>();                               // \expos
    subrange<iterator_t<V>> @\exposid{next_}@ = subrange<iterator_t<V>>();          // \expos
    bool @\exposid{trailing_empty_}@ = false;                                       // \expos
    constexpr @\exposid{iterator}@(split_view& parent, iterator_t<V> current,       // \expos
                       subrange<iterator_t<V>> next);

  public:
    using iterator_concept = forward_iterator_tag;
    using iterator_category = input_iterator_tag;
    using value_type = subrange<iterator_t<V>>;
    using difference_type = range_difference_t<V>;

    @\exposid{iterator}@() = default;

    constexpr iterator_t<V> base() const;
    constexpr value_type operator*() const;

    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
  };
}
\end{codeblock}

\indexlibraryctor{split_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)},
\exposid{cur_} with \tcode{std::move(current)}, and
\exposid{next_} with \tcode{std::move(next)}.
\end{itemdescr}

\indexlibrarymember{base}{split_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<V> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{cur_};}
\end{itemdescr}

\indexlibrarymember{operator*}{split_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr value_type operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \{\exposid{cur_}, \exposid{next_}.begin()\};}
\end{itemdescr}

\indexlibrarymember{operator++}{split_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{cur_}@ = @\exposid{next_}@.begin();
if (@\exposid{cur_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) {
  @\exposid{cur_}@ = @\exposid{next_}@.end();
  if (@\exposid{cur_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) {
    @\exposid{trailing_empty_}@ = true;
    @\exposid{next_}@ = {@\exposid{cur_}@, @\exposid{cur_}@};
  } else {
    @\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{cur_}@);
  }
} else {
  @\exposid{trailing_empty_}@ = false;
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{split_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{split_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.@\exposid{cur_}@ == y.@\exposid{cur_}@ && x.@\exposid{trailing_empty_}@ == y.@\exposid{trailing_empty_}@;
\end{codeblock}
\end{itemdescr}

\rSec3[range.split.sentinel]{Class \tcode{split_view::\exposid{sentinel}}}

\indexlibraryglobal{split_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern>
    requires @\libconcept{view}@<V> && @\libconcept{view}@<Pattern> &&
             @\libconcept{indirectly_comparable}@<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  struct split_view<V, Pattern>::@\exposid{sentinel}@ {
  private:
    sentinel_t<V> @\exposid{end_}@ = sentinel_t<V>();               // \expos
    constexpr explicit @\exposid{sentinel}@(split_view& parent);    // \expos

  public:
    @\exposid{sentinel}@() = default;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y);
  };
}
\end{codeblock}

\indexlibraryctor{split_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(split_view& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{split_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{cur_} == y.\exposid{end_} \&\& !x.\exposid{trailing_empty_};}
\end{itemdescr}

\rSec2[range.concat]{Concat view}

\rSec3[range.concat.overview]{Overview}

\pnum
\tcode{concat_view} presents a view that concatenates all the underlying ranges.

\pnum
The name \tcode{views::concat} denotes
a customization point object\iref{customization.point.object}.
Given a pack of subexpressions \tcode{Es...},
the expression \tcode{views::concat(Es...)} is expression-equivalent to
\begin{itemize}
\item \tcode{views::all(Es...)} if \tcode{Es} is a pack with only one element
whose type models \libconcept{input_range},
\item otherwise, \tcode{concat_view(Es...)}.
\end{itemize}
\begin{example}
\begin{codeblock}
vector<int> v1{1, 2, 3}, v2{4, 5}, v3{};
array a{6, 7, 8};
auto s = views::single(9);
for (auto&& i : views::concat(v1, v2, v3, a, s)) {
  print("{} ", i);      // prints \tcode{1 2 3 4 5 6 7 8 9}
}
\end{codeblock}
\end{example}

\rSec3[range.concat.view]{Class template \tcode{concat_view}}

\indexlibraryglobal{concat_view}%
\begin{codeblock}
namespace std::ranges {
  template<class... Rs>
  using @\exposidnc{concat-reference-t}@ = common_reference_t<range_reference_t<Rs>...>;      // \expos
  template<class... Rs>
  using @\exposidnc{concat-value-t}@ = common_type_t<range_value_t<Rs>...>;                   // \expos
  template<class... Rs>
  using @\exposidnc{concat-rvalue-reference-t}@ =                                             // \expos
    common_reference_t<range_rvalue_reference_t<Rs>...>;

  template<class... Rs>
    concept @\exposconcept{concat-indirectly-readable}@ = @\seebelow@;     // \expos
  template<class... Rs>
    concept @\exposconcept{concatable}@ = @\seebelow@;                     // \expos
  template<bool Const, class... Rs>
    concept @\exposconcept{concat-is-random-access}@ = @\seebelow@;        // \expos
  template<bool Const, class... Rs>
    concept @\exposconcept{concat-is-bidirectional}@ = @\seebelow@;        // \expos

  template<@\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0) &&
              @\exposconcept{concatable}@<Views...>
  class concat_view : public view_interface<concat_view<Views...>> {

    tuple<Views...> @\exposidnc{views_}@;                                             // \expos

    // \ref{range.concat.iterator}, class template \tcode{concat_view::\exposid{iterator}}
    template<bool> class @\exposidnc{iterator}@;                                      // \expos

  public:
    constexpr concat_view() = default;
    constexpr explicit concat_view(Views... views);

    constexpr @\exposid{iterator}@<false> begin() requires (!(@\exposconcept{simple-view}@<Views> && ...));
    constexpr @\exposid{iterator}@<true> begin() const
      requires (@\libconcept{range}@<const Views> && ...) && @\exposconcept{concatable}@<const Views...>;

    constexpr auto end() requires (!(@\exposconcept{simple-view}@<Views> && ...));
    constexpr auto end() const
      requires (@\libconcept{range}@<const Views> && ...) && @\exposconcept{concatable}@<const Views...>;

    constexpr auto size() requires (@\libconcept{sized_range}@<Views> && ...);
    constexpr auto size() const requires (@\libconcept{sized_range}@<const Views> && ...);
    constexpr auto reserve_hint() requires (@\libconcept{approximately_sized_range}@<Views> && ...);
    constexpr auto reserve_hint() const requires (@\libconcept{approximately_sized_range}@<const Views> && ...);
  };

  template<class... R>
    concat_view(R&&...) -> concat_view<views::all_t<R>...>;
}
\end{codeblock}

\begin{itemdecl}
template<class... Rs>
  concept @\defexposconcept{concat-indirectly-readable}@ = @\seebelow@;                           // \expos
\end{itemdecl}

\begin{itemdescr}
\pnum
The exposition-only \exposconcept{concat-indirectly-readable} concept
is equivalent to:
\begin{codeblock}
template<class Ref, class RRef, class It>
  concept @\defexposconcept{concat-indirectly-readable-impl}@ =                         // \expos
    requires (const It it) {
      { *it } -> @\libconcept{convertible_to}@<Ref>;
      { ranges::iter_move(it) } -> @\libconcept{convertible_to}@<RRef>;
    };

template<class... Rs>
  concept @\exposconcept{concat-indirectly-readable}@ =                              // \expos
    @\libconcept{common_reference_with}@<@\exposid{concat-reference-t}@<Rs...>&&,
                          @\exposid{concat-value-t}@<Rs...>&> &&
    @\libconcept{common_reference_with}@<@\exposid{concat-reference-t}@<Rs...>&&,
                          @\exposid{concat-rvalue-reference-t}@<Rs...>&&> &&
    @\libconcept{common_reference_with}@<@\exposid{concat-rvalue-reference-t}@<Rs...>&&,
                          @\exposid{concat-value-t}@<Rs...> const&> &&
    (@\exposconcept{concat-indirectly-readable-impl}@<@\exposid{concat-reference-t}@<Rs...>,
                                     @\exposid{concat-rvalue-reference-t}@<Rs...>,
                                     iterator_t<Rs>> && ...);
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
template<class... Rs>
  concept @\defexposconcept{concatable}@ = @\seebelow@;                                           // \expos
\end{itemdecl}

\begin{itemdescr}
\pnum
The exposition-only \exposconcept{concatable} concept is equivalent to:
\begin{codeblock}
template<class... Rs>
  concept @\exposconcept{concatable}@ = requires {                                   // \expos
    typename @\exposid{concat-reference-t}@<Rs...>;
    typename @\exposid{concat-value-t}@<Rs...>;
    typename @\exposid{concat-rvalue-reference-t}@<Rs...>;
  } && @\exposconcept{concat-indirectly-readable}@<Rs...>;
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
template<bool Const, class... Rs>
  concept @\defexposconcept{concat-is-random-access}@ = @\seebelow@;                              // \expos
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{Fs} be the pack that consists of all elements of \tcode{Rs}
except the last element,
then \exposconceptx{concat-is-ran\-dom-access}{concat-is-random-access}
is equivalent to:
\begin{codeblock}
template<bool Const, class... Rs>
  concept @\exposconcept{concat-is-random-access}@ =                                 // \expos
    @\exposconcept{all-random-access}@<Const, Rs...> &&
    (@\libconcept{common_range}@<@\exposid{maybe-const}@<Const, Fs>> && ...);
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
template<bool Const, class... Rs>
  concept @\defexposconcept{concat-is-bidirectional}@ = @\seebelow@;                              // \expos
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{Fs} be the pack that consists of all elements of \tcode{Rs}
except the last element,
then \exposconceptx{concat-is-bidirec\-tional}{concat-is-bidirectional}
is equivalent to:
\begin{codeblock}
template<bool Const, class... Rs>
  concept @\exposconcept{concat-is-bidirectional}@ =                                 // \expos
    @\exposconcept{all-bidirectional}@<Const, Rs...> &&
    (@\libconcept{common_range}@<@\exposid{maybe-const}@<Const, Fs>> && ...);
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{concat_view}%
\begin{itemdecl}
constexpr explicit concat_view(Views... views);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{views_} with \tcode{std::move(views)...}.
\end{itemdescr}

\indexlibrarymember{begin}{concat_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<false> begin() requires (!(@\exposconcept{simple-view}@<Views> && ...));
constexpr @\exposid{iterator}@<true> begin() const
  requires (@\libconcept{range}@<const Views> && ...) && @\exposconcept{concatable}@<const Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Let \exposid{is-const} be
\tcode{true} for the const-qualified overload, and
\tcode{false} otherwise.
Equivalent to:
\begin{codeblock}
@\exposid{iterator}@<@\exposid{is-const}@> it(this, in_place_index<0>, ranges::begin(std::get<0>(@\exposid{views_}@)));
it.template @\exposid{satisfy}@<0>();
return it;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{concat_view}%
\begin{itemdecl}
constexpr auto end() requires (!(@\exposconcept{simple-view}@<Views> && ...));
constexpr auto end() const
  requires (@\libconcept{range}@<const Views> && ...) && @\exposconcept{concatable}@<const Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Let \exposid{is-const} be
\tcode{true} for the const-qualified overload, and
\tcode{false} otherwise.
Equivalent to:
\begin{codeblock}
constexpr auto N = sizeof...(Views);
if constexpr (@\exposconcept{all-forward}<\exposid{is-const}, Views...>@ &&
              @\libconcept{common_range}@<@\exposid{maybe-const}@<@\exposid{is-const}@, Views...[N - 1]>>) {
  return @\exposid{iterator}@<@\exposid{is-const}@>(this, in_place_index<N - 1>,
                            ranges::end(std::get<N - 1>(@\exposid{views_}@)));
} else {
  return default_sentinel;
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{size}{concat_view}%
\begin{itemdecl}
constexpr auto size() requires (@\libconcept{sized_range}@<Views> && ...);
constexpr auto size() const requires (@\libconcept{sized_range}@<const Views> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply(
  [](auto... sizes) {
    using CT = @\exposid{make-unsigned-like-t}@<common_type_t<decltype(sizes)...>>;
    return (CT(sizes) + ...);
  },
  @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{concat_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires (@\libconcept{approximately_sized_range}@<Views> && ...);
constexpr auto reserve_hint() const requires (@\libconcept{approximately_sized_range}@<const Views> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply(
  [](auto... sizes) {
    using CT = @\exposid{make-unsigned-like-t}@<common_type_t<decltype(sizes)...>>;
    return (CT(sizes) + ...);
  },
  @\exposid{tuple-transform}@(ranges::reserve_hint, @\exposid{views_}@));
\end{codeblock}
\end{itemdescr}

\rSec3[range.concat.iterator]{Class \tcode{concat_view::\exposid{iterator}}}

\indexlibrarymember{iterator}{concat_view}%
\indexlibraryglobal{concat_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0) &&
              @\exposconcept{concatable}@<Views...>
  template<bool Const>
  class concat_view<Views...>::@\exposid{iterator}@ {
  public:
    using iterator_category = @\seebelow@;                                // not always present
    using iterator_concept = @\seebelow@;
    using value_type = @\exposid{concat-value-t}@<@\exposid{maybe-const}@<Const, Views>...>;
    using difference_type = common_type_t<range_difference_t<@\exposid{maybe-const}@<Const, Views>>...>;

  private:
    using @\exposid{base-iter}@ =                                                       // \expos
      variant<iterator_t<@\exposid{maybe-const}@<Const, Views>>...>;

    @\exposid{maybe-const}@<Const, concat_view>* @\exposid{parent_}@ = nullptr;                     // \expos
    @\exposid{base-iter}@ @\exposid{it_}@;                                                          // \expos

    template<size_t N>
      constexpr void @\exposid{satisfy}@();                                             // \expos
    template<size_t N>
      constexpr void @\exposid{prev}@();                                                // \expos

    template<size_t N>
      constexpr void @\exposid{advance-fwd}@(difference_type offset,                    // \expos
                                 difference_type steps);
    template<size_t N>
      constexpr void @\exposid{advance-bwd}@(difference_type offset,                    // \expos
                                 difference_type steps);

    template<class... Args>
      constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@<Const, concat_view>* parent,  // \expos
                                  Args&&... args)
        requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>;

  public:
    @\exposid{iterator}@() = default;

    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && (@\libconcept{convertible_to}@<iterator_t<Views>, iterator_t<const Views>> && ...);

    constexpr decltype(auto) operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int)
      requires @\exposconcept{all-forward}@<Const, Views...>;
    constexpr @\exposid{iterator}@& operator--()
      requires @\exposconcept{concat-is-bidirectional}@<Const, Views...>;
    constexpr @\exposid{iterator}@ operator--(int)
      requires @\exposconcept{concat-is-bidirectional}@<Const, Views...>;
    constexpr @\exposid{iterator}@& operator+=(difference_type n)
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
    constexpr @\exposid{iterator}@& operator-=(difference_type n)
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
    constexpr decltype(auto) operator[](difference_type n) const
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires (@\libconcept{equality_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);
    friend constexpr bool operator==(const @\exposid{iterator}@& it, default_sentinel_t);
    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires (@\exposconcept{all-random-access}@<Const, Views...> &&
                (@\libconcept{three_way_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...));
    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& it, difference_type n)
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& it)
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& it, difference_type n)
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t)
      requires @\seebelow@;
    friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& x)
      requires @\seebelow@;
    friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& it) noexcept(@\seebelow@);
    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(@\seebelow@)
      requires @\seebelow@;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If
\tcode{\exposconcept{concat-is-random-access}<Const, Views...>} is modeled,
then \tcode{iterator_concept} denotes \tcode{ran\-dom_access_iterator_tag}.
\item
Otherwise, if
\tcode{\exposconcept{concat-is-bidirectional}<Const, Views...>} is modeled,
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, if
\tcode{\exposconcept{all-forward}<Const, Views...>} is modeled,
then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if
\tcode{\exposconcept{all-forward}<Const, Views...>} is modeled.
In that case,
\tcode{\exposid{iterator}::iterator_category} is defined as follows:

\begin{itemize}
\item
If
\tcode{is_reference_v<\exposid{concat-reference-t}<\exposid{maybe-const}<Const, Views>...>>}
is \tcode{false},
then \tcode{iter\-ator_category} denotes \tcode{input_iterator_tag}.

\item
Otherwise,
let \tcode{Cs} denote the pack of types
\tcode{iterator_traits<iterator_t<\exposid{maybe-const}<Const, Views>>>::iterator_category...}.
\begin{itemize}
\item
If
\tcode{(\libconcept{derived_from}<Cs, random_access_iterator_tag> \&\& ...) \&\& \exposconceptx{concat-is-random-ac-\linebreak{}cess}{concat-is-random-access}<Const, Views...>}
is \tcode{true},
\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if
\tcode{(\libconcept{derived_from}<Cs, bidirectional_iterator_tag> \&\& ...) \&\& \exposconceptx{concat-is-\linebreak{}bidirectional}{concat-is-bidirectional}<Const, Views...>}
is \tcode{true},
\tcode{iterator_category} denotes \tcode{bidirectional_iter\-ator_tag}.
\item
Otherwise, if
\tcode{(\libconcept{derived_from}<Cs, forward_iterator_tag> \&\& ...)}
is \tcode{true},
\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\end{itemize}
\end{itemize}

\indexlibrarymember{\exposid{satisfy}}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
template<size_t N>
  constexpr void @\exposid{satisfy}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (N < (sizeof...(Views) - 1)) {
  if (std::get<N>(@\exposid{it_}@) == ranges::end(std::get<N>(@\exposid{parent_}@->@\exposid{views_}@))) {
    @\exposid{it_}@.template emplace<N + 1>(ranges::begin(std::get<N + 1>(@\exposid{parent_}@->@\exposid{views_}@)));
    @\exposid{satisfy}@<N + 1>();
  }
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{prev}}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
template<size_t N>
  constexpr void @\exposid{prev}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (N == 0) {
  --std::get<0>(@\exposid{it_}@);
} else {
  if (std::get<N>(@\exposid{it_}@) == ranges::begin(std::get<N>(@\exposid{parent_}@->@\exposid{views_}@))) {
    @\exposid{it_}@.template emplace<N - 1>(ranges::end(std::get<N - 1>(@\exposid{parent_}@->@\exposid{views_}@)));
    @\exposid{prev}@<N - 1>();
  } else {
    --std::get<N>(@\exposid{it_}@);
  }
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{advance-fwd}}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
template<size_t N>
  constexpr void @\exposid{advance-fwd}@(difference_type offset, difference_type steps);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
using underlying_diff_type = iter_difference_t<variant_alternative_t<N, @\exposid{base-iter}@>>;
if constexpr (N == sizeof...(Views) - 1) {
  std::get<N>(@\exposid{it_}@) += static_cast<underlying_diff_type>(steps);
} else {
  auto n_size = ranges::distance(std::get<N>(@\exposid{parent_}@->@\exposid{views_}@));
  if (offset + steps < n_size) {
    std::get<N>(@\exposid{it_}@) += static_cast<underlying_diff_type>(steps);
  } else {
    @\exposid{it_}@.template emplace<N + 1>(ranges::begin(std::get<N + 1>(@\exposid{parent_}@->@\exposid{views_}@)));
    @\exposid{advance-fwd}@<N + 1>(0, offset + steps - n_size);
  }
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{advance-bwd}}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
template<size_t N>
  constexpr void @\exposid{advance-bwd}@(difference_type offset, difference_type steps);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
using underlying_diff_type = iter_difference_t<variant_alternative_t<N, @\exposid{base-iter}@>>;
if constexpr (N == 0) {
  std::get<N>(@\exposid{it_}@) -= static_cast<underlying_diff_type>(steps);
} else {
  if (offset >= steps) {
    std::get<N>(@\exposid{it_}@) -= static_cast<underlying_diff_type>(steps);
  } else {
    auto prev_size = ranges::distance(std::get<N - 1>(@\exposid{parent_}@->@\exposid{views_}@));
    @\exposid{it_}@.template emplace<N - 1>(ranges::end(std::get<N - 1>(@\exposid{parent_}@->@\exposid{views_}@)));
    @\exposid{advance-bwd}@<N - 1>(prev_size, steps - offset);
  }
}
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{concat_view::\exposid{iterator}}%
\begin{itemdecl}
template<class... Args>
  constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@<Const, concat_view>* parent,
                              Args&&... args)
    requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{parent}, and
initializes \exposid{it_} with \tcode{std::forward<Args>(args)...}.
\end{itemdescr}

\indexlibraryctor{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> it)
  requires Const &&
           (@\libconcept{convertible_to}@<iterator_t<Views>, iterator_t<const Views>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Initializes \exposid{parent_} with \tcode{it.\exposid{parent_}}, and
let \tcode{$i$} be \tcode{it.\exposid{it_}.index()},
initializes \exposid{it_} with
\tcode{\exposid{base-iter}(in_place_index<$i$>, std::get<$i$>(std::move(it.\exposid{it_})))}.
\end{itemdescr}

\indexlibrarymember{operator*}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
using reference = @\exposid{concat-reference-t}@<@\exposid{maybe-const}@<Const, Views>...>;
return std::visit([](auto&& it) -> reference { return *it; },
                  @\exposid{it_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Let \tcode{$i$} be \tcode{\exposid{it_}.index()}.
Equivalent to:
\begin{codeblock}
++std::get<@$i$@>(@\exposid{it_}@);
@\exposid{satisfy}@<@$i$@>();
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++*this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int)
  requires @\exposconcept{all-forward}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--()
  requires @\exposconcept{concat-is-bidirectional}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Let \tcode{$i$} be \tcode{\exposid{it_}.index()}.
Equivalent to:
\begin{codeblock}
@\exposid{prev}@<@$i$@>();
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int)
  requires @\exposconcept{concat-is-bidirectional}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n)
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Let \tcode{$i$} be \tcode{\exposid{it_}.index()}.
Equivalent to:
\begin{codeblock}
if (n > 0) {
  @\exposid{advance-fwd}@<@$i$@>(std::get<@$i$@>(@\exposid{it_}@) - ranges::begin(std::get<@$i$@>(@\exposid{parent_}@->@\exposid{views_}@)), n);
} else if (n < 0) {
  @\exposid{advance-bwd}@<@$i$@>(std::get<@$i$@>(@\exposid{it_}@) - ranges::begin(std::get<@$i$@>(@\exposid{parent_}@->@\exposid{views_}@)), -n);
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type n)
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
*this += -n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator[](difference_type n) const
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return *((*this) + n);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires (@\libconcept{equality_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x.\exposid{it_}.valueless_by_exception()} and
\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.@\exposid{it_}@ == y.@\exposid{it_}@;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& it, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
constexpr auto last_idx = sizeof...(Views) - 1;
return it.@\exposid{it_}@.index() == last_idx &&
       std::get<last_idx>(it.@\exposid{it_}@) == ranges::end(std::get<last_idx>(it.@\exposid{parent_}@->@\exposid{views_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator<}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires (@\exposconcept{all-random-access}@<Const, Views...> &&
            (@\libconcept{three_way_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...));
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x.\exposid{it_}.valueless_by_exception()} and
\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}.

\pnum
Let \tcode{$op$} be the operator.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.@\exposid{it_}@ @$op$@ y.@\exposid{it_}@;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& it, difference_type n)
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = it;
temp += n;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& it)
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return it + n;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& it, difference_type n)
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = it;
temp -= n;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{concat-is-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x.\exposid{it_}.valueless_by_exception()} and
\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}.

\pnum
\effects
Let
\tcode{$i_\tcode{x}$} denote \tcode{x.\exposid{it_}.index()} and
\tcode{$i_\tcode{y}$} denote \tcode{y.\exposid{it_}.index()}.

\begin{itemize}
\item
%FIXME This is hard to parse.
If \tcode{$i_\tcode{x}$ > $i_\tcode{y}$}, let
\tcode{$d_\tcode{y}$} be
\tcode{ranges::distance(std::get<$i_\tcode{y}$>(y.\exposid{it_}), ranges::end(std::get<$i_\tcode{y}$>(y.\linebreak{}\exposid{parent_}->\exposid{views_})))},
\tcode{$d_\tcode{x}$} be
\tcode{ranges::distance(ranges::begin(std::get<$i_\tcode{x}$>(x.\exposid{parent_}->\linebreak{}\exposid{views_})), std::get<$i_\tcode{x}$>(x.\exposid{it_}))}.
Let \tcode{$s$} denote the sum of the sizes of all the ranges
\tcode{std::get<\linebreak{}$i$>(x.\exposid{parent_}->\exposid{views_})}
for every integer \tcode{$i$} in the range
\range{$i_\tcode{y}$ + 1}{$i_\tcode{x}$}
if there is any, and
\tcode{0} otherwise,
of type \tcode{difference_type},
equivalent to:
\begin{codeblock}
return @$d_\tcode{y}$@ + @$s$@ + @$d_\tcode{x}$@;
\end{codeblock}

\item
otherwise, if \tcode{$i_\tcode{x}$ < $i_\tcode{y}$} is \tcode{true},
equivalent to:
\begin{codeblock}
return -(y - x);
\end{codeblock}

\item
otherwise, equivalent to:
\begin{codeblock}
return std::get<@$i_\tcode{x}$@>(x.@\exposid{it_}@) - std::get<@$i_\tcode{y}$@>(y.@\exposid{it_}@);
\end{codeblock}
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t)
  requires @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x.\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
%FIXME This is hard to parse.
Let
\tcode{$i_\tcode{x}$} denote \tcode{x.\exposid{it_}.index()},
\tcode{$d_\tcode{x}$} be
\tcode{ranges::distance(std::get<$i_\tcode{x}$>(x.\exposid{it_}), ranges::\linebreak{}end(std::get<$i_\tcode{x}$>(x.\exposid{parent_}->\exposid{views_})))}.
Let \tcode{$s$} denote the sum of the sizes of all the ranges
\tcode{std::get<$i$>(x.\exposid{parent_}->\exposid{views_})}
for every integer \tcode{$i$} in the range
\range{$i_\tcode{x}$ + 1}{sizeof...(Views)}
if there is any, and
\tcode{0} otherwise,
of type difference_type,
equivalent to:
\begin{codeblock}
return -(@$d_\tcode{x}$@ + @$s$@);
\end{codeblock}

\pnum
\remarks
Let \tcode{Fs} be the pack that consists of all elements of \tcode{Views}
except the first element,
%FIXME Do we want \grammarterm{expression} here? Same elsewhere?
the expression in the \grammarterm{requires-clause} is equivalent to:
\begin{codeblock}
(@\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                    iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...) &&
(@\libconcept{sized_range}@<@\exposid{maybe-const}@<Const, Fs>> && ...)
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& x)
  requires @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return -(x - default_sentinel);
\end{codeblock}

\pnum
\remarks
Let \tcode{Fs} be the pack that consists of all elements of \tcode{Views}
except the first element,
the expression in the \grammarterm{requires-clause} is equivalent to:
\begin{codeblock}
(@\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                    iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...) &&
(@\libconcept{sized_range}@<@\exposid{maybe-const}@<Const, Fs>> && ...)
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{iter_move}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& it) noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return std::visit([](const auto& i)
                  -> @\exposid{concat-rvalue-reference-t}@<@\exposid{maybe-const}@<Const, Views>...> {
                    return ranges::iter_move(i);
                  },
                  it.@\exposid{it_}@);
\end{codeblock}

\pnum
\remarks
The exception specification is equivalent to:
\begin{codeblock}
((is_nothrow_invocable_v<decltype(ranges::iter_move),
                         const iterator_t<@\exposid{maybe-const}@<Const, Views>>&> &&
  is_nothrow_convertible_v<range_rvalue_reference_t<@\exposid{maybe-const}@<Const, Views>>,
                           @\exposid{concat-rvalue-reference-t}@<@\exposid{maybe-const}@<Const, Views>...>>) &&
 ...)
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{iter_swap}{concat_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(@\seebelow@)
  requires @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x.\exposid{it_}.valueless_by_exception()} and
\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
std::visit([&](const auto& it1, const auto& it2) {
             if constexpr (is_same_v<decltype(it1), decltype(it2)>) {
               ranges::iter_swap(it1, it2);
             } else {
               ranges::swap(*x, *y);
             }
           },
           x.@\exposid{it_}@, y.@\exposid{it_}@);
\end{codeblock}

\pnum
\remarks
The exception specification is equivalent to
\begin{codeblock}
(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its)))
\end{codeblock}
where \tcode{its} is a pack of lvalues of type
%FIXME "respectively" doesn't make sense here.
\tcode{const iterator_t<\exposid{maybe-const}<Const, Views>>} respectively.

\par % This paragraph is part of the \remarks clause.
The expression in the \grammarterm{requires-clause} is equivalent to
\begin{codeblock}
@\libconcept{swappable_with}@<iter_reference_t<@\exposid{iterator}@>, iter_reference_t<@\exposid{iterator}@>> &&
(... && @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>>)
\end{codeblock}
\end{itemdescr}

\rSec2[range.counted]{Counted view}

\pnum
\indextext{range!counted}%
A counted view presents a view of the elements
of the counted range\iref{iterator.requirements.general} \countedrange{i}{n}
for an iterator \tcode{i} and non-negative integer \tcode{n}.

\pnum
\indexlibrarymember{counted}{views}%
The name \tcode{views::counted} denotes
a customization point object\iref{customization.point.object}.
Let \tcode{E} and \tcode{F} be expressions,
let \tcode{T} be \tcode{decay_t<decltype((E))>}, and
let \tcode{D} be \tcode{iter_difference_t<T>}.
If \tcode{decltype((F))} does not model
\tcode{\libconcept{convertible_to}<D>},
\tcode{views::counted(E, F)} is ill-formed.
\begin{note}
This case can result in substitution failure
when \tcode{views::counted(E, F)}
appears in the immediate context of a template instantiation.
\end{note}
Otherwise, \tcode{views::counted(E, F)}
is expression-equivalent to:

\begin{itemize}
\item
If \tcode{T} models \libconcept{contiguous_iterator},
then \tcode{span(to_address(E), static_cast<size_t>(static_-\linebreak{}cast<D>(F)))}.

\item
Otherwise, if \tcode{T} models \libconcept{random_access_iterator},
then \tcode{subrange(E, E + static_cast<D>(F))},
except that \tcode{E} is evaluated only once.

\item
Otherwise,
\tcode{subrange(counted_iterator(E, F), default_sentinel)}.
\end{itemize}

\rSec2[range.common]{Common view}

\rSec3[range.common.overview]{Overview}

\pnum
\tcode{common_view} takes a view which has different types for
its iterator and sentinel and turns it into a view of the same
elements with an iterator and sentinel of the same type.

\pnum
\begin{note}
\tcode{common_view} is useful for calling legacy algorithms that expect
a range's iterator and sentinel types to be the same.
\end{note}

\pnum
\indexlibrarymember{common}{views}%
The name \tcode{views::common} denotes a
range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E},
the expression \tcode{views::common(E)} is expression-equivalent to:
\begin{itemize}
\item \tcode{views::all(E)},
  if \tcode{decltype((E))} models \libconcept{common_range}
  and \tcode{views::all(E)} is a well-formed expression.

\item Otherwise, \tcode{common_view\{E\}}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
// Legacy algorithm:
template<class ForwardIterator>
size_t count(ForwardIterator first, ForwardIterator last);

template<@\libconcept{forward_range}@ R>
void my_algo(R&& r) {
  auto&& common = views::common(r);
  auto cnt = count(common.begin(), common.end());
  // ...
}
\end{codeblock}
\end{example}

\rSec3[range.common.view]{Class template \tcode{common_view}}

\indexlibraryglobal{common_view}%
\indexlibrarymember{base}{common_view}%
\indexlibrarymember{size}{common_view}%
\indexlibrarymember{begin}{common_view}%
\indexlibrarymember{end}{common_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires (!@\libconcept{common_range}@<V> && @\libconcept{copyable}@<iterator_t<V>>)
  class common_view : public view_interface<common_view<V>> {
  private:
    V @\exposid{base_}@ = V();  // \expos

  public:
    common_view() requires @\libconcept{default_initializable}@<V> = default;

    constexpr explicit common_view(V r);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{random_access_range}@<V> && @\libconcept{sized_range}@<V>)
        return ranges::begin(@\exposid{base_}@);
      else
        return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(@\exposid{base_}@));
    }

    constexpr auto begin() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{random_access_range}@<const V> && @\libconcept{sized_range}@<const V>)
        return ranges::begin(@\exposid{base_}@);
      else
        return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(@\exposid{base_}@));
    }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{random_access_range}@<V> && @\libconcept{sized_range}@<V>)
        return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@);
      else
        return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(@\exposid{base_}@));
    }

    constexpr auto end() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{random_access_range}@<const V> && @\libconcept{sized_range}@<const V>)
        return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@);
      else
        return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(@\exposid{base_}@));
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V> {
      return ranges::size(@\exposid{base_}@);
    }
    constexpr auto size() const requires @\libconcept{sized_range}@<const V> {
      return ranges::size(@\exposid{base_}@);
    }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V> {
      return ranges::reserve_hint(@\exposid{base_}@);
    }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V> {
      return ranges::reserve_hint(@\exposid{base_}@);
    }
  };

  template<class R>
    common_view(R&&) -> common_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{common_view}%
\begin{itemdecl}
constexpr explicit common_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec2[range.reverse]{Reverse view}

\rSec3[range.reverse.overview]{Overview}

\pnum
\tcode{reverse_view} takes a bidirectional view and produces
another view that iterates the same elements in reverse order.

\pnum
\indexlibrarymember{reverse}{views}%
The name \tcode{views::reverse} denotes a
range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E}, the expression
\tcode{views::reverse(E)} is expression-equivalent to:
\begin{itemize}
\item
  If the type of \tcode{E} is
  a (possibly cv-qualified) specialization of \tcode{reverse_view},
  then \tcode{E.base()}.

\item
  Otherwise, if \tcode{E} is a specialization of \tcode{optional} and \tcode{E}
  models \libconcept{view}, then \tcode{\exposidnc{decay-copy}(E)}.

\item
  Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange<reverse_iterator<I>, reverse_iterator<I>, K>}
  for some iterator type \tcode{I} and
  value \tcode{K} of type \tcode{subrange_kind},
  \begin{itemize}
  \item
    if \tcode{K} is \tcode{subrange_kind::sized}, then
\tcode{subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())};
  \item
    otherwise, \tcode{subrange<I, I, K>(E.end().base(), E.begin().base())}.
  \end{itemize}
  However, in either case \tcode{E} is evaluated only once.
\item
  Otherwise, \tcode{reverse_view\{E\}}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
vector<int> is {0,1,2,3,4};
for (int i : is | views::reverse)
  cout << i << ' '; // prints \tcode{4 3 2 1 0}
\end{codeblock}
\end{example}

\rSec3[range.reverse.view]{Class template \tcode{reverse_view}}

\indexlibraryglobal{reverse_view}%
\indexlibrarymember{base}{reverse_view}%
\indexlibrarymember{size}{reverse_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{bidirectional_range}@<V>
  class reverse_view : public view_interface<reverse_view<V>> {
  private:
    V @\exposid{base_}@ = V();  // \expos

  public:
    reverse_view() requires @\libconcept{default_initializable}@<V> = default;

    constexpr explicit reverse_view(V r);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr reverse_iterator<iterator_t<V>> begin();
    constexpr reverse_iterator<iterator_t<V>> begin() requires @\libconcept{common_range}@<V>;
    constexpr auto begin() const requires @\libconcept{common_range}@<const V>;

    constexpr reverse_iterator<iterator_t<V>> end();
    constexpr auto end() const requires @\libconcept{common_range}@<const V>;

    constexpr auto size() requires @\libconcept{sized_range}@<V> {
      return ranges::size(@\exposid{base_}@);
    }

    constexpr auto size() const requires @\libconcept{sized_range}@<const V> {
      return ranges::size(@\exposid{base_}@);
    }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V> {
      return ranges::reserve_hint(@\exposid{base_}@);
    }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V> {
      return ranges::reserve_hint(@\exposid{base_}@);
    }
  };

  template<class R>
    reverse_view(R&&) -> reverse_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{reverse_view}%
\begin{itemdecl}
constexpr explicit reverse_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\indexlibrarymember{begin}{reverse_view}%
\begin{itemdecl}
constexpr reverse_iterator<iterator_t<V>> begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
make_reverse_iterator(ranges::next(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)))
\end{codeblock}

\pnum
\remarks
In order to provide the amortized constant time complexity required by
the \libconcept{range} concept, this function caches the result within the
\tcode{reverse_view} for use on subsequent calls.
\end{itemdescr}

\indexlibrarymember{begin}{reverse_view}%
\begin{itemdecl}
constexpr reverse_iterator<iterator_t<V>> begin() requires @\libconcept{common_range}@<V>;
constexpr auto begin() const requires @\libconcept{common_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return make_reverse_iterator(ranges::end(\exposid{base_}));}
\end{itemdescr}

\indexlibrarymember{end}{reverse_view}%
\begin{itemdecl}
constexpr reverse_iterator<iterator_t<V>> end();
constexpr auto end() const requires @\libconcept{common_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return make_reverse_iterator(ranges::begin(\exposid{base_}));}
\end{itemdescr}

\rSec2[range.as.const]{As const view}

\rSec3[range.as.const.overview]{Overview}

\pnum
\tcode{as_const_view} presents a view of an underlying sequence as constant.
That is, the elements of an \tcode{as_const_view} cannot be modified.

\pnum
The name \tcode{views::as_const} denotes
a range adaptor object\iref{range.adaptor.object}.
Let \tcode{E} be an expression,
let \tcode{T} be \tcode{decltype((E))}, and
let \tcode{U} be \tcode{remove_cvref_t<T>}.
The expression \tcode{views::as_const(E)} is expression-equivalent to:
\begin{itemize}
\item
If \tcode{views::all_t<T>} models \libconcept{constant_range},
then \tcode{views::all(E)}.
\item
Otherwise,
if \tcode{U} denotes \tcode{empty_view<X>}
for some type \tcode{X}, then \tcode{auto(views::empty<const X>)}.

\item
Otherwise, if \tcode{U} denotes \tcode{optional<X\&>}
for some type \tcode{X}, then \tcode{optional<const X\&>(E)}.

\item
Otherwise,
if \tcode{U} denotes \tcode{span<X, Extent>}
for some type \tcode{X} and some extent \tcode{Extent},
then \tcode{span<const X, Extent>(E)}.
\item
Otherwise,
if \tcode{U} denotes \tcode{ref_view<X>} for some type \tcode{X} and
\tcode{const X} models \libconcept{constant_range},
then \tcode{ref_view(static_cast<const X\&>(E.base()))}.
\item
Otherwise,
if \tcode{E} is an lvalue,
\tcode{const U} models \libconcept{constant_range}, and
\tcode{U} does not model \libconcept{view},
then \tcode{ref_view(static_cast<const U\&>(E))}.
\item
Otherwise, \tcode{as_const_view(E)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
template<@\libconcept{constant_range}@ R>
void cant_touch_this(R&&);

vector<char> hammer = {'m', 'c'};
span<char> beat = hammer;
cant_touch_this(views::as_const(beat));         // will not modify the elements of \tcode{hammer}
\end{codeblock}
\end{example}

\rSec3[range.as.const.view]{Class template \tcode{as_const_view}}

\indexlibraryglobal{as_const_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class as_const_view : public view_interface<as_const_view<V>> {
    V @\exposid{base_}@ = V();      // \expos

  public:
    as_const_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit as_const_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>) { return ranges::cbegin(@\exposid{base_}@); }
    constexpr auto begin() const requires @\libconcept{range}@<const V> { return ranges::cbegin(@\exposid{base_}@); }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) { return ranges::cend(@\exposid{base_}@); }
    constexpr auto end() const requires @\libconcept{range}@<const V> { return ranges::cend(@\exposid{base_}@); }

    constexpr auto size() requires @\libconcept{sized_range}@<V> { return ranges::size(@\exposid{base_}@); }
    constexpr auto size() const requires @\libconcept{sized_range}@<const V> { return ranges::size(@\exposid{base_}@); }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
  };

  template<class R>
    as_const_view(R&&) -> as_const_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{as_const_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit as_const_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec2[range.elements]{Elements view}

\rSec3[range.elements.overview]{Overview}

\pnum
\tcode{elements_view} takes
a view of tuple-like values and a \tcode{size_t}, and
produces a view with a value-type of the $N^\text{th}$ element
of the adapted view's value-type.

\pnum
\indexlibrarymember{elements}{views}%
The name \tcode{views::elements<N>} denotes
a range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E} and constant expression \tcode{N},
the expression \tcode{views::elements<N>(E)} is expression-equivalent to
\tcode{elements_view<views::all_t<decltype((E))>, N>\{E\}}.

\begin{example}
\begin{codeblock}
auto historical_figures = map{
  pair{"Lovelace"sv, 1815},
  {"Turing"sv, 1912},
  {"Babbage"sv, 1791},
  {"Hamilton"sv, 1936}
};

auto names = historical_figures | views::elements<0>;
for (auto&& name : names) {
  cout << name << ' ';          // prints \tcode{Babbage Hamilton Lovelace Turing }
}

auto birth_years = historical_figures | views::elements<1>;
for (auto&& born : birth_years) {
  cout << born << ' ';          // prints \tcode{1791 1936 1815 1912 }
}
\end{codeblock}
\end{example}

\pnum
\tcode{keys_view} is an alias for \tcode{elements_view<R, 0>}, and
is useful for extracting keys from associative containers.

\begin{example}
\begin{codeblock}
auto names = historical_figures | views::keys;
for (auto&& name : names) {
  cout << name << ' ';          // prints \tcode{Babbage Hamilton Lovelace Turing }
}
\end{codeblock}
\end{example}

\pnum
\tcode{values_view} is an alias for \tcode{elements_view<R, 1>}, and
is useful for extracting values from associative containers.

\begin{example}
\begin{codeblock}
auto is_even = [](const auto x) { return x % 2 == 0; };
cout << ranges::count_if(historical_figures | views::values, is_even);  // prints \tcode{2}
\end{codeblock}
\end{example}

\rSec3[range.elements.view]{Class template \tcode{elements_view}}

\indexlibraryglobal{elements_view}%
\indexlibrarymember{base}{elements_view}%
\indexlibrarymember{begin}{elements_view}%
\indexlibrarymember{end}{elements_view}%
\indexlibrarymember{size}{elements_view}%
\begin{codeblock}
namespace std::ranges {
  template<class T, size_t N>
  concept @\defexposconcept{has-tuple-element}@ =                   // \expos
    @\exposconcept{tuple-like}@<T> && N < tuple_size_v<T> &&
    requires(T t) {
      { std::get<N>(t) } -> @\libconcept{convertible_to}@<const tuple_element_t<N, T>&>;
    };

  template<class T, size_t N>
  concept @\defexposconcept{returnable-element}@ =                  // \expos
    is_reference_v<T> || @\libconcept{move_constructible}@<tuple_element_t<N, T>>;

  template<@\libconcept{input_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && @\exposconcept{has-tuple-element}@<range_value_t<V>, N> &&
             @\exposconcept{has-tuple-element}@<remove_reference_t<range_reference_t<V>>, N> &&
             @\exposconcept{returnable-element}@<range_reference_t<V>, N>
  class elements_view : public view_interface<elements_view<V, N>> {
  public:
    elements_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit elements_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>)
    { return @\exposid{iterator}@<false>(ranges::begin(@\exposid{base_}@)); }

    constexpr auto begin() const requires @\libconcept{range}@<const V>
    { return @\exposid{iterator}@<true>(ranges::begin(@\exposid{base_}@)); }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V> && !@\libconcept{common_range}@<V>)
    { return @\exposid{sentinel}@<false>{ranges::end(@\exposid{base_}@)}; }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V> && @\libconcept{common_range}@<V>)
    { return @\exposid{iterator}@<false>{ranges::end(@\exposid{base_}@)}; }

    constexpr auto end() const requires @\libconcept{range}@<const V>
    { return @\exposid{sentinel}@<true>{ranges::end(@\exposid{base_}@)}; }

    constexpr auto end() const requires @\libconcept{common_range}@<const V>
    { return @\exposid{iterator}@<true>{ranges::end(@\exposid{base_}@)}; }

    constexpr auto size() requires @\libconcept{sized_range}@<V>
    { return ranges::size(@\exposid{base_}@); }

    constexpr auto size() const requires @\libconcept{sized_range}@<const V>
    { return ranges::size(@\exposid{base_}@); }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>
    { return ranges::reserve_hint(@\exposid{base_}@); }

    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>
    { return ranges::reserve_hint(@\exposid{base_}@); }

  private:
    // \ref{range.elements.iterator}, class template \tcode{elements_view::\exposid{iterator}}
    template<bool> class @\exposid{iterator}@;                      // \expos

    // \ref{range.elements.sentinel}, class template \tcode{elements_view::\exposid{sentinel}}
    template<bool> class @\exposid{sentinel}@;                      // \expos

    V @\exposid{base_}@ = V();                                      // \expos
  };
}
\end{codeblock}

\indexlibraryctor{elements_view}%
\begin{itemdecl}
constexpr explicit elements_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec3[range.elements.iterator]{Class template \tcode{elements_view::\exposid{iterator}}}

\indexlibraryglobal{elements_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && @\exposconcept{has-tuple-element}@<range_value_t<V>, N> &&
             @\exposconcept{has-tuple-element}@<remove_reference_t<range_reference_t<V>>, N> &&
             @\exposconcept{returnable-element}@<range_reference_t<V>, N>
  template<bool Const>
  class elements_view<V, N>::@\exposid{iterator}@ {
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                 // \expos

    iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>();     // \expos

    static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i);     // \expos
    constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current);                      // \expos

  public:
    using iterator_concept = @\seebelow@;
    using iterator_category = @\seebelow@;                // not always present
    using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<@\exposid{Base}@>>>;
    using difference_type = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposid{Base}@>> = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
    constexpr iterator_t<@\exposid{Base}@> base() &&;

    constexpr decltype(auto) operator*() const
    { return @\exposid{get-element}@(@\exposid{current_}@); }

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr decltype(auto) operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>
    { return @\exposid{get-element}@(@\exposid{current_}@ + n); }

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_concept}
is defined as follows:
\begin{itemize}
\item
If \exposid{Base} models \libconcept{random_access_range},
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{forward_range},
then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if \exposid{Base} models \libconcept{forward_range}.
In that case, \tcode{iterator_category} is defined as follows:
Let \tcode{C} denote the type
\tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}.
\begin{itemize}
\item
If \tcode{std::get<N>(*\exposid{current_})} is an rvalue,
\tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\item
Otherwise, if \tcode{C} models \tcode{\libconcept{derived_from}<random_access_iterator_tag>},
\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, \tcode{iterator_category} denotes \tcode{C}.
\end{itemize}

\indexlibrarymember{\exposid{get-element}}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (is_reference_v<range_reference_t<@\exposid{Base}@>>) {
  return std::get<N>(*i);
} else {
  using E = remove_cv_t<tuple_element_t<N, range_reference_t<@\exposid{Base}@>>>;
  return static_cast<E>(std::get<N>(*i));
}
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)}.
\end{itemdescr}

\indexlibraryctor{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{base}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{current_};}
\end{itemdescr}

\indexlibrarymember{base}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return std::move(\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{++\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = *this;
++@\exposid{current_}@;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = *this;
--@\exposid{current_}@;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ += n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ -= n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator<}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} < y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator>}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator+}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}\{x\} += y;}
\end{itemdescr}

\indexlibrarymember{operator+}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y + x;}
\end{itemdescr}

\indexlibrarymember{operator-}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}\{x\} -= y;}
\end{itemdescr}

\indexlibrarymember{operator-}{elements_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};}
\end{itemdescr}

\rSec3[range.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}}

\indexlibraryglobal{elements_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && @\exposconcept{has-tuple-element}@<range_value_t<V>, N> &&
             @\exposconcept{has-tuple-element}@<remove_reference_t<range_reference_t<V>>, N> &&
             @\exposconcept{returnable-element}@<range_reference_t<V>, N>
  template<bool Const>
  class elements_view<V, N>::@\exposid{sentinel}@ {
  private:
    using @\exposid{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                 // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();         // \expos
    constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);  // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> other)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr sentinel_t<@\exposid{Base}@> base() const;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
  };
}
\end{codeblock}

\indexlibraryctor{elements_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end}.
\end{itemdescr}

\indexlibraryctor{elements_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> other)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{base}{elements_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr sentinel_t<@\exposid{Base}@> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator==}{elements_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{elements_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{elements_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};}
\end{itemdescr}

\rSec2[range.enumerate]{Enumerate view}

\rSec3[range.enumerate.overview]{Overview}

\pnum
\indexlibraryglobal{enumerate_view}%
\tcode{enumerate_view} is a view whose
elements represent both the position and value from
a sequence of elements.

\pnum
\indexlibrarymember{enumerate}{views}%
The name \tcode{views::enumerate} denotes a range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E},
the expression \tcode{views::enumerate(E)} is expression-equivalent to
\tcode{enumerate_view<views::all_t<decltype((E))>>(E)}.
\begin{example}
\begin{codeblock}
vector<int> vec{ 1, 2, 3 };
for (auto [index, value] : views::enumerate(vec))
  cout << index << ":" << value << ' ';         // prints \tcode{0:1 1:2 2:3}
\end{codeblock}
\end{example}

\rSec3[range.enumerate.view]{Class template \tcode{enumerate_view}}

\indexlibraryglobal{enumerate_view}%
\indexlibrarymember{begin}{enumerate_view}%
\indexlibrarymember{end}{enumerate_view}%
\indexlibrarymember{size}{enumerate_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\exposconcept{range-with-movable-references}@<V>
  class enumerate_view : public view_interface<enumerate_view<V>> {
    V @\exposidnc{base_}@ = V();                                    // \expos

    // \ref{range.enumerate.iterator}, class template \tcode{enumerate_view::\exposid{iterator}}
    template<bool Const>
      class @\exposidnc{iterator}@;                                 // \expos

    // \ref{range.enumerate.sentinel}, class template \tcode{enumerate_view::\exposid{sentinel}}
    template<bool Const>
      class @\exposidnc{sentinel}@;                                 // \expos

  public:
    constexpr enumerate_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit enumerate_view(V base);

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>)
    { return @\exposid{iterator}@<false>(ranges::begin(@\exposid{base_}@), 0); }
    constexpr auto begin() const requires @\exposconcept{range-with-movable-references}@<const V>
    { return @\exposid{iterator}@<true>(ranges::begin(@\exposid{base_}@), 0); }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{forward_range}@<V> && @\libconcept{common_range}@<V> && @\libconcept{sized_range}@<V>)
        return @\exposid{iterator}@<false>(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@));
      else
        return @\exposid{sentinel}@<false>(ranges::end(@\exposid{base_}@));
    }
    constexpr auto end() const requires @\exposconcept{range-with-movable-references}@<const V> {
      if constexpr (@\libconcept{forward_range}@<const V> && @\libconcept{common_range}@<const V> && @\libconcept{sized_range}@<const V>)
        return @\exposid{iterator}@<true>(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@));
      else
        return @\exposid{sentinel}@<true>(ranges::end(@\exposid{base_}@));
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V>
    { return ranges::size(@\exposid{base_}@); }
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>
    { return ranges::size(@\exposid{base_}@); }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>
    { return ranges::reserve_hint(@\exposid{base_}@); }
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>
    { return ranges::reserve_hint(@\exposid{base_}@); }

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }
  };

  template<class R>
    enumerate_view(R&&) -> enumerate_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{enumerate_view}%
\begin{itemdecl}
constexpr explicit enumerate_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec3[range.enumerate.iterator]{Class template \tcode{enumerate_view::\exposid{iterator}}}

\indexlibraryglobal{enumerate_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\exposconcept{range-with-movable-references}@<V>
  template<bool Const>
  class enumerate_view<V>::@\exposid{iterator}@ {
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                         // \expos

  public:
    using iterator_category = input_iterator_tag;
    using iterator_concept = @\seebelow@;
    using difference_type = range_difference_t<@\exposid{Base}@>;
    using value_type = tuple<difference_type, range_value_t<@\exposid{Base}@>>;

  private:
    using @\exposidnc{reference-type}@ =                                      // \expos
      tuple<difference_type, range_reference_t<@\exposid{Base}@>>;
    iterator_t<@\exposidnc{Base}@> @\exposidnc{current_}@ = iterator_t<@\exposidnc{Base}@>();             // \expos
    difference_type @\exposidnc{pos_}@ = 0;                                   // \expos

    constexpr explicit
      @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> current, difference_type pos);  // \expos

  public:
    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposid{Base}@>> = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
    constexpr iterator_t<@\exposid{Base}@> base() &&;

    constexpr difference_type index() const noexcept;

    constexpr auto operator*() const {
      return @\exposid{reference-type}@(@\exposid{pos_}@, *@\exposid{current_}@);
    }

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr auto operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>
    { return @\exposid{reference-type}@(@\exposid{pos_}@ + n, @\exposid{current_}@[n]); }

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept;
    friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept;

    friend constexpr auto iter_move(const @\exposid{iterator}@& i)
      noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)) &&
               is_nothrow_move_constructible_v<range_rvalue_reference_t<@\exposid{Base}@>>) {
      return tuple<difference_type,
                   range_rvalue_reference_t<@\exposid{Base}@>>(i.@\exposid{pos_}@, ranges::iter_move(i.@\exposid{current_}@));
    }
  };
}
\end{codeblock}

\pnum
The member \grammarterm{typedef-name}
\tcode{\exposid{iterator}::iterator_concept}
is defined as follows:
\begin{itemize}
\item
If \exposid{Base} models \libconcept{random_access_range},
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{forward_range},
then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\indexlibraryctor{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, difference_type pos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)} and
\exposid{pos_} with \tcode{pos}.
\end{itemdescr}

\indexlibraryctor{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and
\exposid{pos_} with \tcode{i.\exposid{pos_}}.
\end{itemdescr}

\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{current_};}
\end{itemdescr}

\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return std::move(\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{index}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr difference_type index() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{pos_};}
\end{itemdescr}

\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{current_}@;
++@\exposid{pos_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = *this;
++*this;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{current_}@;
--@\exposid{pos_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = *this;
--*this;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ += n;
@\exposid{pos_}@ += n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ -= n;
@\exposid{pos_}@ -= n;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{pos_} == y.\exposid{pos_};}
\end{itemdescr}

\indexlibrarymember{operator<=>}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{pos_} <=> y.\exposid{pos_};}
\end{itemdescr}

\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = x;
temp += y;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y + x;}
\end{itemdescr}

\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto temp = x;
temp -= y;
return temp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{pos_} - y.\exposid{pos_};}
\end{itemdescr}

\rSec3[range.enumerate.sentinel]{Class template \tcode{enumerate_view::\exposid{sentinel}}}

\indexlibraryglobal{enumerate_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\exposconcept{range-with-movable-references}@<V>
  template<bool Const>
  class enumerate_view<V>::@\exposid{sentinel}@ {
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                         // \expos
    sentinel_t<@\exposidnc{Base}@> @\exposidnc{end_}@ = sentinel_t<@\exposidnc{Base}@>();                 // \expos
    constexpr explicit @\exposidnc{sentinel}@(sentinel_t<@\exposidnc{Base}@> end);          // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> other)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr sentinel_t<@\exposid{Base}@> base() const;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
  };
}
\end{codeblock}

\indexlibraryctor{enumerate_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(end)}.
\end{itemdescr}

\indexlibraryctor{enumerate_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> other)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{base}{enumerate_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr sentinel_t<@\exposid{Base}@> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator==}{enumerate_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};}
\end{itemdescr}

\rSec2[range.zip]{Zip view}

\rSec3[range.zip.overview]{Overview}

\pnum
\indexlibraryglobal{zip_view}%
\tcode{zip_view} takes any number of views and
produces a view of tuples of references
to the corresponding elements of the constituent views.

\pnum
\indexlibrarymember{zip}{views}%
The name \tcode{views::zip} denotes
a customization point object\iref{customization.point.object}.
Given a pack of subexpressions \tcode{Es...},
the expression \tcode{views::zip(Es...)} is expression-equivalent to
\begin{itemize}
\item
\tcode{auto(views::empty<tuple<>>)}
if \tcode{Es} is an empty pack,
\item
otherwise, \tcode{zip_view<views::all_t<decltype((Es))>...>(Es...)}.
\end{itemize}

\begin{example}
\begin{codeblock}
vector v = {1, 2};
list l = {'a', 'b', 'c'};

auto z = views::zip(v, l);
range_reference_t<decltype(z)> f = z.front();   // \tcode{f} is a \tcode{tuple<int\&, char\&>}
                                                // that refers to the first element of \tcode{v} and \tcode{l}

for (auto&& [x, y] : z) {
  cout << '(' << x << ", " << y << ") ";        // prints \tcode{(1, a) (2, b)}
}
\end{codeblock}
\end{example}

\rSec3[range.zip.view]{Class template \tcode{zip_view}}

\indexlibraryglobal{zip_view}%
\indexlibrarymember{begin}{zip_view}%
\indexlibrarymember{end}{zip_view}%
\begin{codeblock}
namespace std::ranges {
  template<class... Rs>
  concept @\defexposconcept{zip-is-common}@ =                             // \expos
    (sizeof...(Rs) == 1 && (@\libconcept{common_range}@<Rs> && ...)) ||
    (!(@\libconcept{bidirectional_range}@<Rs> && ...) && (@\libconcept{common_range}@<Rs> && ...)) ||
    ((@\libconcept{random_access_range}@<Rs> && ...) && (@\libconcept{sized_range}@<Rs> && ...));

  template<@\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0)
  class zip_view : public view_interface<zip_view<Views...>> {
    tuple<Views...> @\exposid{views_}@;             // \expos

    // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}}
    template<bool> class @\exposidnc{iterator}@;      // \expos

    // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}}
    template<bool> class @\exposidnc{sentinel}@;      // \expos

  public:
    zip_view() = default;
    constexpr explicit zip_view(Views... views);

    constexpr auto begin() requires (!(@\exposconcept{simple-view}@<Views> && ...)) {
      return @\exposid{iterator}@<false>(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@));
    }
    constexpr auto begin() const requires (@\libconcept{range}@<const Views> && ...) {
      return @\exposid{iterator}@<true>(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@));
    }

    constexpr auto end() requires (!(@\exposconcept{simple-view}@<Views> && ...)) {
      if constexpr (!@\exposconcept{zip-is-common}@<Views...>) {
        return @\exposid{sentinel}@<false>(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@));
      } else if constexpr ((@\libconcept{random_access_range}@<Views> && ...)) {
        return begin() + iter_difference_t<@\exposid{iterator}@<false>>(size());
      } else {
        return @\exposid{iterator}@<false>(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@));
      }
    }

    constexpr auto end() const requires (@\libconcept{range}@<const Views> && ...) {
      if constexpr (!@\exposconcept{zip-is-common}@<const Views...>) {
        return @\exposid{sentinel}@<true>(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@));
      } else if constexpr ((@\libconcept{random_access_range}@<const Views> && ...)) {
        return begin() + iter_difference_t<@\exposid{iterator}@<true>>(size());
      } else {
        return @\exposid{iterator}@<true>(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@));
      }
    }

    constexpr auto size() requires (@\libconcept{sized_range}@<Views> && ...);
    constexpr auto size() const requires (@\libconcept{sized_range}@<const Views> && ...);
  };

  template<class... Rs>
    zip_view(Rs&&...) -> zip_view<views::all_t<Rs>...>;
}
\end{codeblock}

\pnum
Two \tcode{zip_view} objects have the same underlying sequence if and only if
the corresponding elements of \exposid{views_} are equal\iref{concepts.equality}
and have the same underlying sequence.
\begin{note}
In particular, comparison of iterators obtained from \tcode{zip_view} objects
that do not have the same underlying sequence
is not required to produce meaningful results\iref{iterator.concept.forward}.
\end{note}

\indexlibraryctor{zip_view}%
\begin{itemdecl}
constexpr explicit zip_view(Views... views);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{views_} with \tcode{std::move(views)...}.
\end{itemdescr}

\indexlibrarymember{size}{zip_view}%
\begin{itemdecl}
constexpr auto size() requires (@\libconcept{sized_range}@<Views> && ...);
constexpr auto size() const requires (@\libconcept{sized_range}@<const Views> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply([](auto... sizes) {
  using CT = @\exposid{make-unsigned-like-t}@<common_type_t<decltype(sizes)...>>;
  return ranges::min({CT(sizes)...});
}, @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@));
\end{codeblock}
\end{itemdescr}

\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}}

\indexlibraryglobal{zip_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0)
  template<bool Const>
  class zip_view<Views...>::@\exposid{iterator}@ {
    tuple<iterator_t<@\exposidnc{maybe-const}@<Const, Views>>...> @\exposid{current_}@;@\itcorr[-1]@       // \expos
    constexpr explicit @\exposidnc{iterator}@(tuple<iterator_t<@\exposidnc{maybe-const}@<Const, Views>>...>);
                                                                            // \expos
  public:
    using iterator_category = input_iterator_tag;                           // not always present
    using iterator_concept  = @\seebelow@;
    using value_type = tuple<range_value_t<@\exposid{maybe-const}@<Const, Views>>...>;
    using difference_type = common_type_t<range_difference_t<@\exposid{maybe-const}@<Const, Views>>...>;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && (@\libconcept{convertible_to}@<iterator_t<Views>, iterator_t<const Views>> && ...);

    constexpr auto operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@<Const, Views...>;

    constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@<Const, Views...>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@<Const, Views...>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\exposconcept{all-random-access}@<Const, Views...>;

    constexpr auto operator[](difference_type n) const
      requires @\exposconcept{all-random-access}@<Const, Views...>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires (@\libconcept{equality_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);

    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{all-random-access}@<Const, Views...>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
      requires @\exposconcept{all-random-access}@<Const, Views...>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires (@\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>,
                                   iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);

    friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@);

    friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@)
      requires (@\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \tcode{\exposconcept{all-random-access}<Const, Views...>} is modeled,
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise,
if \tcode{\exposconcept{all-bidirectional}<Const, Views...>} is modeled,
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise,
if \tcode{\exposconcept{all-forward}<Const, Views...>} is modeled,
then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
\tcode{\exposid{iterator}::iterator_category} is present
if and only if \tcode{\exposconcept{all-forward}<Const, Views...>} is modeled.

\pnum
If the invocation of any non-const member function of \exposid{iterator}
exits via an exception,
the iterator acquires a singular value.

\indexlibraryctor{zip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(tuple<iterator_t<@\exposid{maybe-const}@<Const, Views>>...> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)}.
\end{itemdescr}

\indexlibraryctor{zip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && (@\libconcept{convertible_to}@<iterator_t<Views>, iterator_t<const Views>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{operator*}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{tuple-for-each}@([&]<class I>(I& i) { i += iter_difference_t<I>(x); }, @\exposid{current_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{tuple-for-each}@([&]<class I>(I& i) { i -= iter_difference_t<I>(x); }, @\exposid{current_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator[](difference_type n) const
  requires @\exposconcept{all-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{tuple-transform}@([&]<class I>(I& i) -> decltype(auto) {
  return i[iter_difference_t<I>(n)];
}, @\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires (@\libconcept{equality_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{x.\exposid{current_} == y.\exposid{current_}}
if \tcode{\exposconcept{all-bidirectional}<Const, Views...>} is \tcode{true}.
\item
Otherwise, \tcode{true}
if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$
such that \tcode{bool(std::\brk{}get<$i$>(x.\exposid{current_}) ==
std::get<$i$>(y.\exposid{current_}))} is \tcode{true}.
\begin{note}
This allows \tcode{zip_view} to model \libconcept{common_range}
when all constituent views model \libconcept{common_range}.
\end{note}
\item
Otherwise, \tcode{false}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator<=>}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} <=> y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator+}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r += n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\exposconcept{all-random-access}@<Const, Views...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r -= n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires (@\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>,
                               iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}.

\pnum
\returns
The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)}
for all integers $0 \leq n < \tcode{sizeof...(Views)}$.
\end{itemdescr}

\indexlibrarymember{iter_move}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@);
\end{codeblock}

\pnum
\remarks
The exception specification is equivalent to:
\begin{codeblock}
(noexcept(ranges::iter_move(declval<const iterator_t<@\exposid{maybe-const}@<Const,
                                                            Views>>&>())) && ...) &&
(is_nothrow_move_constructible_v<range_rvalue_reference_t<@\exposid{maybe-const}@<Const,
                                                                      Views>>> && ...)
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{iter_swap}{izip_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@)
  requires (@\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, Views>>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
For every integer $0 \leq i < \tcode{sizeof...(Views)}$,
performs:
\begin{codeblock}
ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))
\end{codeblock}

\pnum
\remarks
The exception specification is equivalent to
the logical \logop{and} of the following expressions:
\begin{codeblock}
noexcept(ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)))
\end{codeblock}
for every integer $0 \leq i < \tcode{sizeof...(Views)}$.
\end{itemdescr}

\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}}

\indexlibraryglobal{zip_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0)
  template<bool Const>
  class zip_view<Views...>::@\exposid{sentinel}@ {
    tuple<sentinel_t<@\exposidnc{maybe-const}@<Const, Views>>...> @\exposid{end_}@;@\itcorr[-1]@               // \expos
    constexpr explicit @\exposidnc{sentinel}@(tuple<sentinel_t<@\exposidnc{maybe-const}@<Const, Views>>...> end);
                                                                                // \expos
  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
      requires Const && (@\libconcept{convertible_to}@<sentinel_t<Views>, sentinel_t<const Views>> && ...);

    template<bool OtherConst>
      requires (@\libconcept{sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                             iterator_t<@\exposid{maybe-const}@<OtherConst, Views>>> && ...)
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires (@\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                                   iterator_t<@\exposid{maybe-const}@<OtherConst, Views>>> && ...)
    friend constexpr common_type_t<range_difference_t<@\exposid{maybe-const}@<OtherConst, Views>>...>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires (@\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                                   iterator_t<@\exposid{maybe-const}@<OtherConst, Views>>> && ...)
    friend constexpr common_type_t<range_difference_t<@\exposid{maybe-const}@<OtherConst, Views>>...>
      operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<OtherConst>& x);
  };
}
\end{codeblock}

\indexlibraryctor{zip_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(tuple<sentinel_t<@\exposid{maybe-const}@<Const, Views>>...> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end}.
\end{itemdescr}

\indexlibraryctor{zip_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
  requires Const && (@\libconcept{convertible_to}@<sentinel_t<Views>, sentinel_t<const Views>> && ...);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{zip_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires (@\libconcept{sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                         iterator_t<@\exposid{maybe-const}@<OtherConst, Views>>> && ...)
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$
such that \tcode{bool(std::get<$i$>(x.\brk{}\exposid{current_}) ==
std::get<$i$>(y.\exposid{end_}))} is \tcode{true}.
Otherwise, \tcode{false}.
\end{itemdescr}

\indexlibrarymember{operator-}{zip_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires (@\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                               iterator_t<@\exposid{maybe-const}@<OtherConst, Views>>> && ...)
friend constexpr common_type_t<range_difference_t<@\exposid{maybe-const}@<OtherConst, Views>>...>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{D} be the return type.
Let \tcode{\exposid{DIST}($i$)} be
\tcode{D(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{end_}))}.

\pnum
\returns
The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)}
for all integers $0 \leq n < \tcode{sizeof...(Views)}$.
\end{itemdescr}

\indexlibrarymember{operator-}{zip_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires (@\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{maybe-const}@<Const, Views>>,
                               iterator_t<@\exposid{maybe-const}@<OtherConst, Views>>> && ...)
friend constexpr common_type_t<range_difference_t<@\exposid{maybe-const}@<OtherConst, Views>>...>
  operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<OtherConst>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(x - y);}
\end{itemdescr}

\rSec2[range.zip.transform]{Zip transform view}

\rSec3[range.zip.transform.overview]{Overview}

\pnum
\indexlibraryglobal{zip_transform_view}%
\tcode{zip_transform_view} takes an invocable object and
any number of views and
produces a view
whose $M^\text{th}$ element is
the result of applying the invocable object
to the $M^\text{th}$ elements of all views.

\pnum
\indexlibrarymember{zip_transform}{views}%
The name \tcode{views::zip_transform} denotes
a customization point object\iref{customization.point.object}.
Let \tcode{F} be a subexpression, and
let \tcode{Es...} be a pack of subexpressions.
\begin{itemize}
\item
If \tcode{Es} is an empty pack,
let \tcode{FD} be \tcode{decay_t<decltype((F))>}.
\begin{itemize}
\item
If \tcode{\libconcept{move_constructible}<FD> \&\&
\libconcept{regular_invocable}<FD\&>} is \tcode{false}, or
if \tcode{decay_t<invoke_result_t<FD\&>>} is not an object type,
\tcode{views::zip_transform(F, Es...)} is ill-formed.
\item
Otherwise, the expression \tcode{views::zip_transform(F, Es...)}
is expression-equivalent to
\begin{codeblock}
((void)F, auto(views::empty<decay_t<invoke_result_t<FD&>>>))
\end{codeblock}
\end{itemize}
\item
Otherwise, the expression \tcode{views::zip_transform(F, Es...)}
is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
vector v1 = {1, 2};
vector v2 = {4, 5, 6};

for (auto i : views::zip_transform(plus(), v1, v2)) {
  cout << i << ' ';     // prints \tcode{5 7}
}
\end{codeblock}
\end{example}

\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}}

\indexlibraryglobal{zip_transform_view}%
\indexlibrarymember{begin}{zip_transform_view}%
\indexlibrarymember{end}{zip_transform_view}%
\indexlibrarymember{size}{zip_transform_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
              @\libconcept{regular_invocable}@<F&, range_reference_t<Views>...> &&
              @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<Views>...>>
  class zip_transform_view : public view_interface<zip_transform_view<F, Views...>> {
    @\exposidnc{movable-box}@<F> @\exposid{fun_}@;                    // \expos
    zip_view<Views...> @\exposid{zip_}@;                // \expos

    using @\exposidnc{InnerView}@ = zip_view<Views...>;   // \expos
    template<bool Const>
      using @\exposidnc{ziperator}@ = iterator_t<@\exposidnc{maybe-const}@<Const, @\exposidnc{InnerView}@>>;      // \expos
    template<bool Const>
      using @\exposidnc{zentinel}@ = sentinel_t<@\exposidnc{maybe-const}@<Const, @\exposidnc{InnerView}@>>;       // \expos

    // \ref{range.zip.transform.iterator}, class template \tcode{zip_transform_view::\exposid{iterator}}
    template<bool> class @\exposidnc{iterator}@;          // \expos

    // \ref{range.zip.transform.sentinel}, class template \tcode{zip_transform_view::\exposid{sentinel}}
    template<bool> class @\exposidnc{sentinel}@;          // \expos

  public:
    zip_transform_view() = default;

    constexpr explicit zip_transform_view(F fun, Views... views);

    constexpr auto begin() { return @\exposid{iterator}@<false>(*this, @\exposid{zip_}@.begin()); }

    constexpr auto begin() const
      requires @\libconcept{range}@<const @\exposid{InnerView}@> &&
               @\libconcept{regular_invocable}@<const F&, range_reference_t<const Views>...> {
      return @\exposid{iterator}@<true>(*this, @\exposid{zip_}@.begin());
    }

    constexpr auto end() {
      if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) {
        return @\exposid{iterator}@<false>(*this, @\exposid{zip_}@.end());
      } else {
        return @\exposid{sentinel}@<false>(@\exposid{zip_}@.end());
      }
    }

    constexpr auto end() const
      requires @\libconcept{range}@<const @\exposid{InnerView}@> &&
               @\libconcept{regular_invocable}@<const F&, range_reference_t<const Views>...> {
      if constexpr (@\libconcept{common_range}@<const @\exposid{InnerView}@>) {
        return @\exposid{iterator}@<true>(*this, @\exposid{zip_}@.end());
      } else {
        return @\exposid{sentinel}@<true>(@\exposid{zip_}@.end());
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> {
      return @\exposid{zip_}@.size();
    }

    constexpr auto size() const requires @\libconcept{sized_range}@<const @\exposid{InnerView}@> {
      return @\exposid{zip_}@.size();
    }
  };

  template<class F, class... Rs>
    zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>;
}
\end{codeblock}

\indexlibraryctor{zip_transform_view}%
\begin{itemdecl}
constexpr explicit zip_transform_view(F fun, Views... views);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{fun_} with \tcode{std::move(fun)} and
\exposid{zip_} with \tcode{std::move(views)...}.
\end{itemdescr}

\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}}

\indexlibraryglobal{zip_transform_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
              @\libconcept{regular_invocable}@<F&, range_reference_t<Views>...> &&
              @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<Views>...>>
  template<bool Const>
  class zip_transform_view<F, Views...>::@\exposid{iterator}@ {
    using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@<Const, zip_transform_view>;      // \expos
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, @\exposidnc{InnerView}@>;                 // \expos
    @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr;                                  // \expos
    @\exposid{ziperator}@<Const> @\exposid{inner_}@;@\itcorr[-1]@                                    // \expos

    constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@<Const> inner);   // \expos

  public:
    using iterator_category = @\seebelownc@;                        // not always present
    using iterator_concept  = @\exposid{ziperator}@<Const>::iterator_concept;
    using value_type =
      remove_cvref_t<invoke_result_t<@\exposid{maybe-const}@<Const, F>&,
                                     range_reference_t<@\exposid{maybe-const}@<Const, Views>>...>>;
    using difference_type = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@<false>, @\exposid{ziperator}@<Const>>;

    constexpr decltype(auto) operator*() const noexcept(@\seebelow@);
    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr decltype(auto) operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@<Const>>;

    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@<Const>, @\exposid{ziperator}@<Const>>;
  };
}
\end{codeblock}

\pnum
The member \grammarterm{typedef-name}
\tcode{\exposid{iterator}::iterator_category}
is declared if and only if \exposid{Base} models \libconcept{forward_range}.
In that case,
\tcode{\exposid{iterator}::iterator_category} is defined as follows:
\begin{itemize}
\item
If
\begin{codeblock}
invoke_result_t<@\exposid{maybe-const}@<Const, F>&, range_reference_t<@\exposid{maybe-const}@<Const, Views>>...>
\end{codeblock}
is not a reference,
\tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\item
Otherwise, let \tcode{Cs} denote the pack of types
\tcode{iterator_traits<iterator_t<\exposid{maybe-const}<Const, Views>>>::iterator_category...}.
\begin{itemize}
\item
If \tcode{(\libconcept{derived_from}<Cs, random_access_iterator_tag> \&\& ...)}
is \tcode{true},
\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise,
if \tcode{(\libconcept{derived_from}<Cs, bidirectional_iterator_tag> \&\& ...)}
is \tcode{true},
\tcode{iterator\-_category} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise,
if \tcode{(\libconcept{derived_from}<Cs, forward_iterator_tag> \&\& ...)}
is \tcode{true},
\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\end{itemize}
\end{itemize}

\indexlibraryctor{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@<Const> inner);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)} and
\exposid{inner_} with \tcode{std::move(inner)}.
\end{itemdescr}

\indexlibraryctor{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@<false>, @\exposid{ziperator}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and
\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}.
\end{itemdescr}

\indexlibrarymember{operator*}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator*() const noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply([&](const auto&... iters) -> decltype(auto) {
  return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...);
}, @\exposid{inner_}@.@\exposid{current_}@);
\end{codeblock}

\pnum
\remarks
Let \tcode{Is} be the pack \tcode{0, 1, \ldots, \tcode{(sizeof...(Views) - 1)}}.
The exception specification is equivalent to:
\tcode{noexcept(invoke(*\exposid{parent_}->\exposid{fun_}, *std::get<Is>(\exposid{inner_}.\exposid{current_})...))}.
\end{itemdescr}

\indexlibrarymember{operator++}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{inner_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{inner_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{inner_}@ += x;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{inner_}@ -= x;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator[](difference_type n) const
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply([&]<class... Is>(const Is&... iters) -> decltype(auto) {
  return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[iter_difference_t<Is>(n)]...);
}, @\exposid{inner_}@.@\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@<Const>>;
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\effects
Equivalent to:
\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};}
\end{itemdescr}

\indexlibrarymember{operator+}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);}
\end{itemdescr}

\indexlibrarymember{operator-}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);}
\end{itemdescr}

\indexlibrarymember{operator-}{zip_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@<Const>, @\exposid{ziperator}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return x.\exposid{inner_} - y.\exposid{inner_};}
\end{itemdescr}

\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}}

\indexlibraryglobal{zip_transform_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views>
    requires (@\libconcept{view}@<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
              @\libconcept{regular_invocable}@<F&, range_reference_t<Views>...> &&
              @\exposconcept{can-reference}@<invoke_result_t<F&, range_reference_t<Views>...>>
  template<bool Const>
  class zip_transform_view<F, Views...>::@\exposid{sentinel}@ {
    @\exposidnc{zentinel}@<Const> @\exposid{inner_}@;                                     // \expos
    constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{zentinel}@<Const> inner);         // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@<false>, @\exposid{zentinel}@<Const>>;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@<Const>, @\exposid{ziperator}@<OtherConst>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@<Const>, @\exposid{ziperator}@<OtherConst>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@<Const>, @\exposid{ziperator}@<OtherConst>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
      operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
  };
}
\end{codeblock}

\indexlibraryctor{zip_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@<Const> inner);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{inner_} with \tcode{inner}.
\end{itemdescr}

\indexlibraryctor{zip_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@<false>, @\exposid{zentinel}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{zip_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@<Const>, @\exposid{ziperator}@<OtherConst>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};}
\end{itemdescr}

\indexlibrarymember{operator-}{zip_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@<Const>, @\exposid{ziperator}@<OtherConst>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@<Const>, @\exposid{ziperator}@<OtherConst>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
  operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};}
\end{itemdescr}

\rSec2[range.adjacent]{Adjacent view}

\rSec3[range.adjacent.overview]{Overview}

\pnum
\tcode{adjacent_view} takes a view and
produces a view whose $M^\text{th}$ element is
a tuple of references to
the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements of
the original view.
If the original view has fewer than $N$ elements, the resulting view is empty.

\pnum
\indexlibrarymember{adjacent}{views}%
The name \tcode{views::adjacent<N>} denotes
a range adaptor object\iref{range.adaptor.object}.
Given a subexpression \tcode{E} and a constant expression \tcode{N},
the expression \tcode{views::adjacent<N>(E)} is expression-equivalent to
\begin{itemize}
\item
\tcode{((void)E, auto(views::empty<tuple<>>))}
if \tcode{N} is equal to \tcode{0} and
\tcode{decltype((E))} models \libconcept{forward_range},
\item
otherwise, \tcode{adjacent_view<views::all_t<decltype((E))>, N>(E)}.
\end{itemize}

\begin{example}
\begin{codeblock}
vector v = {1, 2, 3, 4};

for (auto i : v | views::adjacent<2>) {
  cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") ";  // prints \tcode{(1, 2) (2, 3) (3, 4)}
}
\end{codeblock}
\end{example}

\pnum
Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types,
each of which denotes the same type as \tcode{T}.

\rSec3[range.adjacent.view]{Class template \tcode{adjacent_view}}

\indexlibraryglobal{adjacent_view}%
\indexlibrarymember{begin}{adjacent_view}%
\indexlibrarymember{end}{adjacent_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && (N > 0)
  class adjacent_view : public view_interface<adjacent_view<V, N>> {
    V @\exposid{base_}@ = V();                      // \expos

    // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}}
    template<bool> class @\exposidnc{iterator}@;      // \expos

    // \ref{range.adjacent.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}}
    template<bool> class @\exposidnc{sentinel}@;      // \expos

    struct @\exposidnc{as-sentinel}@{};               // \expos

  public:
    adjacent_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit adjacent_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>) {
      return @\exposid{iterator}@<false>(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@));
    }

    constexpr auto begin() const requires @\libconcept{range}@<const V> {
      return @\exposid{iterator}@<true>(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@));
    }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{common_range}@<V>) {
        return @\exposid{iterator}@<false>(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@));
      } else {
        return @\exposid{sentinel}@<false>(ranges::end(@\exposid{base_}@));
      }
    }

    constexpr auto end() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{common_range}@<const V>) {
        return @\exposid{iterator}@<true>(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@));
      } else {
        return @\exposid{sentinel}@<true>(ranges::end(@\exposid{base_}@));
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };
}
\end{codeblock}

\indexlibraryctor{adjacent_view}%
\begin{itemdecl}
constexpr explicit adjacent_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\indexlibrarymember{size}{adjacent_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
using ST = decltype(ranges::size(@\exposid{base_}@));
using CT = common_type_t<ST, size_t>;
auto sz = static_cast<CT>(ranges::size(@\exposid{base_}@));
sz -= std::min<CT>(sz, N - 1);
return static_cast<ST>(sz);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{adjacent_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
using DT = range_difference_t<decltype((@\exposid{base_}@))>;
using CT = common_type_t<DT, size_t>;
auto sz = static_cast<CT>(ranges::reserve_hint(@\exposid{base_}@));
sz -= std::min<CT>(sz, N - 1);
return @\exposid{to-unsigned-like}@(sz);
\end{codeblock}
\end{itemdescr}

\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}}

\indexlibraryglobal{adjacent_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && (N > 0)
  template<bool Const>
  class adjacent_view<V, N>::@\exposid{iterator}@ {
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                                         // \expos
    array<iterator_t<@\exposidnc{Base}@>, N> @\exposid{current_}@ = array<iterator_t<@\exposidnc{Base}@>, N>();         // \expos
    constexpr @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> first, sentinel_t<@\exposidnc{Base}@> last);          // \expos
    constexpr @\exposidnc{iterator}@(@\exposidnc{as-sentinel}@, iterator_t<@\exposidnc{Base}@> first, iterator_t<@\exposidnc{Base}@> last);
                                                                                // \expos
  public:
    using iterator_category = input_iterator_tag;
    using iterator_concept  = @\seebelow@;
    using value_type = tuple<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>;
    using difference_type = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr auto operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr auto operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> &&
               @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;

    friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@);
    friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@)
      requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \exposid{Base} models \libconcept{random_access_range},
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\end{itemize}

\pnum
If the invocation of any non-const member function of \exposid{iterator}
exits via an exception, the \exposid{iterator} acquires a singular value.

\indexlibraryctor{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{\exposid{current_}[0] == first} is \tcode{true}, and
for every integer $1 \leq i < \tcode{N}$,
\tcode{\exposid{current_}[$i$] == ranges::next(\exposid{current_}[$i$-1], 1, last)}
is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
If \exposid{Base} does not model \libconcept{bidirectional_range},
each element of \exposid{current_} is equal to \exposid{last}.
Otherwise, \tcode{\exposid{current_}[N-1] == last} is \tcode{true}, and
for every integer $0 \leq i < (\tcode{N} - 1)$,
\tcode{\exposid{current_}[$i$] == ranges::prev(\exposid{current_}[$i$+1], 1, first)}
is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes each element of \exposid{current_}
with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue.
\end{itemdescr}

\indexlibrarymember{operator*}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_}.back()} is incrementable.

\pnum
\ensures
Each element of \exposid{current_} is equal to \tcode{ranges::next(i)},
where \tcode{i} is the value of that element before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_}.front()} is decrementable.

\pnum
\ensures
Each element of \exposid{current_} is equal to \tcode{ranges::prev(i)},
where \tcode{i} is the value of that element before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator--}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_}.back() + x} has well-defined behavior.

\pnum
\ensures
Each element of \exposid{current_} is equal to \tcode{i + x},
where \tcode{i} is the value of that element before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator-=}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_}.front() - x} has well-defined behavior.

\pnum
\ensures
Each element of \exposid{current_} is equal to \tcode{i - x},
where \tcode{i} is the value of that element before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator[]}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator[](difference_type n) const
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}.
\end{itemdescr}

\indexlibrarymember{operator<}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_}.back() < y.\exposid{current_}.back()}.
\end{itemdescr}

\indexlibrarymember{operator>}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> &&
           @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}.
\end{itemdescr}

\indexlibrarymember{operator+}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r += n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r -= n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return x.\exposid{current_}.back() - y.\exposid{current_}.back();}
\end{itemdescr}

\indexlibrarymember{iter_move}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});}

\pnum
\remarks
The exception specification is equivalent to:
\begin{codeblock}
noexcept(ranges::iter_move(declval<const iterator_t<@\exposid{Base}@>&>())) &&
is_nothrow_move_constructible_v<range_rvalue_reference_t<@\exposid{Base}@>>
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{iter_swap}{adjacent_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@)
  requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
None of the iterators in \tcode{l.\exposid{current_}} is equal to
an iterator in \tcode{r.\exposid{current_}}.

\pnum
\effects
For every integer $0 \leq i < \tcode{N}$,
performs
\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}.

\pnum
\remarks
The exception specification is equivalent to:
\begin{codeblock}
noexcept(ranges::iter_swap(declval<iterator_t<@\exposid{Base}@>>(), declval<iterator_t<@\exposid{Base}@>>()))
\end{codeblock}
\end{itemdescr}

\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}}

\indexlibraryglobal{adjacent_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, size_t N>
    requires @\libconcept{view}@<V> && (N > 0)
  template<bool Const>
  class adjacent_view<V, N>::@\exposid{sentinel}@ {
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                         // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();                 // \expos
    constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);          // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
      operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<OtherConst>& x);
  };
}
\end{codeblock}

\indexlibraryctor{adjacent_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end}.
\end{itemdescr}

\indexlibraryctor{adjacent_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{adjacent_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{maybe-const}@<OtherConst, V>>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, V>>
  operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<OtherConst>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();}
\end{itemdescr}

\rSec2[range.adjacent.transform]{Adjacent transform view}

\rSec3[range.adjacent.transform.overview]{Overview}

\pnum
\tcode{adjacent_transform_view} takes an invocable object and
a view and produces a view
whose $M^\text{th}$ element is the result of applying the invocable object
to the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements
of the original view.
If the original view has fewer than $N$ elements, the resulting view is empty.

\pnum
\indexlibrarymember{adjacent_transform}{views}%
The name \tcode{views::adjacent_transform<N>} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F} and
a constant expression \tcode{N}:
\begin{itemize}
\item
If \tcode{N} is equal to \tcode{0} and
\tcode{decltype((E))} models \libconcept{forward_range},
\tcode{views::adjacent_transform<N>(E, F)} is expression-equivalent to
\tcode{((void)E, views::zip_transform(F))},
except that the evaluations of \tcode{E} and \tcode{F} are
indeterminately sequenced.
\item
Otherwise,
the expression \tcode{views::adjacent_transform<N>(E, F)} is
expression-equivalent to
\tcode{adja\-cent_transform_view<views::all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
vector v = {1, 2, 3, 4};

for (auto i : v | views::adjacent_transform<2>(std::multiplies())) {
  cout << i << ' ';     // prints \tcode{2 6 12}
}
\end{codeblock}
\end{example}

\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}}

\indexlibraryglobal{adjacent_transform_view}%
\indexlibrarymember{base}{adjacent_transform_view}%
\indexlibrarymember{begin}{adjacent_transform_view}%
\indexlibrarymember{end}{adjacent_transform_view}%
\indexlibrarymember{size}{adjacent_transform_view}%
\indexlibrarymember{reserve_hint}{adjacent_transform_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N>
    requires @\libconcept{view}@<V> && (N > 0) && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, @\exposid{REPEAT}@(range_reference_t<V>, N)...> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, @\exposid{REPEAT}@(range_reference_t<V>, N)...>>
  class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {
    @\exposidnc{movable-box}@<F> @\exposid{fun_}@;                        // \expos
    adjacent_view<V, N> @\exposid{inner_}@;                 // \expos

    using @\exposidnc{InnerView}@ = adjacent_view<V, N>;      // \expos
    template<bool Const>
      using @\exposid{inner-iterator}@ = iterator_t<@\exposid{maybe-const}@<Const, @\exposid{InnerView}@>>;         // \expos
    template<bool Const>
      using @\exposid{inner-sentinel}@ = sentinel_t<@\exposid{maybe-const}@<Const, @\exposid{InnerView}@>>;         // \expos

    // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}}
    template<bool> class @\exposidnc{iterator}@;              // \expos

    // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}}
    template<bool> class @\exposidnc{sentinel}@;              // \expos

  public:
    adjacent_transform_view() = default;
    constexpr explicit adjacent_transform_view(V base, F fun);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{inner_}@.base(); }
    constexpr V base() && { return std::move(@\exposid{inner_}@).base(); }

    constexpr auto begin() {
      return @\exposid{iterator}@<false>(*this, @\exposid{inner_}@.begin());
    }

    constexpr auto begin() const
      requires @\libconcept{range}@<const @\exposid{InnerView}@> &&
               @\libconcept{regular_invocable}@<const F&, @\exposid{REPEAT}@(range_reference_t<const V>, N)...> {
      return @\exposid{iterator}@<true>(*this, @\exposid{inner_}@.begin());
    }

    constexpr auto end() {
      if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) {
        return @\exposid{iterator}@<false>(*this, @\exposid{inner_}@.end());
      } else {
        return @\exposid{sentinel}@<false>(@\exposid{inner_}@.end());
      }
    }

    constexpr auto end() const
      requires @\libconcept{range}@<const @\exposid{InnerView}@> &&
               @\libconcept{regular_invocable}@<const F&, @\exposid{REPEAT}@(range_reference_t<const V>, N)...> {
      if constexpr (@\libconcept{common_range}@<const @\exposid{InnerView}@>) {
        return @\exposid{iterator}@<true>(*this, @\exposid{inner_}@.end());
      } else {
        return @\exposid{sentinel}@<true>(@\exposid{inner_}@.end());
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> {
      return @\exposid{inner_}@.size();
    }

    constexpr auto size() const requires @\libconcept{sized_range}@<const @\exposid{InnerView}@> {
      return @\exposid{inner_}@.size();
    }

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<@\exposid{InnerView}@> {
      return @\exposid{inner_}@.reserve_hint();
    }

    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const @\exposid{InnerView}@> {
      return @\exposid{inner_}@.reserve_hint();
    }
  };
}
\end{codeblock}

\indexlibraryctor{adjacent_transform_view}%
\begin{itemdecl}
constexpr explicit adjacent_transform_view(V base, F fun);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{fun_} with \tcode{std::move(fun)} and
\exposid{inner_} with \tcode{std::move(base)}.
\end{itemdescr}

\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}}

\indexlibraryglobal{adjacent_transform_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N>
    requires @\libconcept{view}@<V> && (N > 0) && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, @\exposid{REPEAT}@(range_reference_t<V>, N)...> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, @\exposid{REPEAT}@(range_reference_t<V>, N)...>>
  template<bool Const>
  class adjacent_transform_view<V, F, N>::@\exposid{iterator}@ {
    using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@<Const, adjacent_transform_view>;         // \expos
    using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@<Const, V>;                                 // \expos
    @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr;                                          // \expos
    @\exposidnc{inner-iterator}@<Const> @\exposid{inner_}@;                                       // \expos

    constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{inner-iterator}@<Const> inner);    // \expos

  public:
    using iterator_category = @\seebelow@;
    using iterator_concept  = @\exposid{inner-iterator}@<Const>::iterator_concept;
    using value_type =
      remove_cvref_t<invoke_result_t<@\exposid{maybe-const}@<Const, F>&,
                                     @\exposid{REPEAT}@(range_reference_t<@\exposid{Base}@>, N)...>>;
    using difference_type = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@<false>, @\exposid{inner-iterator}@<Const>>;

    constexpr decltype(auto) operator*() const noexcept(@\seebelow@);
    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);
    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr decltype(auto) operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@<Const>>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@<Const>, @\exposid{inner-iterator}@<Const>>;
  };
}
\end{codeblock}

\pnum
The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category}
is defined as follows:
\begin{itemize}
\item
If \tcode{invoke_result_t<\exposid{maybe-const}<Const, F>\&,
\exposid{REPEAT}(range_reference_t<\exposid{Base}>, N)...>}
is\linebreak not a reference,
\tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\item
Otherwise, let \tcode{C} denote the type
\tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}.
\begin{itemize}
\item
If \tcode{\libconcept{derived_from}<C, random_access_iterator_tag>}
is \tcode{true},
\tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}.
\item
Otherwise,
if \tcode{\libconcept{derived_from}<C, bidirectional_iterator_tag>}
is \tcode{true},
\tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise,
if \tcode{\libconcept{derived_from}<C, forward_iterator_tag>}
is \tcode{true},
\tcode{iterator_category} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}.
\end{itemize}
\end{itemize}

\indexlibraryctor{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@<Const> inner);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)} and
\exposid{inner_} with \tcode{std::move(inner)}.
\end{itemdescr}

\indexlibraryctor{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@<false>, @\exposid{inner-iterator}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and
\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}.
\end{itemdescr}

\indexlibrarymember{operator*}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator*() const noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply([&](const auto&... iters) -> decltype(auto) {
  return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...);
}, @\exposid{inner_}@.@\exposid{current_}@);
\end{codeblock}

\pnum
\remarks
Let \tcode{Is} be the pack \tcode{0, 1, \ldots, (N - 1)}.
The exception specification is equivalent to:
\begin{codeblock}
noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get<Is>(@\exposid{inner_}@.@\exposid{current_}@)...))
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{inner_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
--@\exposid{inner_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{inner_}@ += x;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{inner_}@ -= x;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr decltype(auto) operator[](difference_type n) const
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply([&](const auto&... iters) -> decltype(auto) {
  return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[n]...);
}, @\exposid{inner_}@.@\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\effects
Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};}
\end{itemdescr}

\indexlibrarymember{operator+}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_transform_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@<Const>, @\exposid{inner-iterator}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};}
\end{itemdescr}

\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}}

\indexlibraryglobal{adjacent_transform_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N>
    requires @\libconcept{view}@<V> && (N > 0) && is_object_v<F> &&
             @\libconcept{regular_invocable}@<F&, @\exposid{REPEAT}@(range_reference_t<V>, N)...> &&
             @\exposconcept{can-reference}@<invoke_result_t<F&, @\exposid{REPEAT}@(range_reference_t<V>, N)...>>
  template<bool Const>
  class adjacent_transform_view<V, F, N>::@\exposid{sentinel}@ {
    @\exposidnc{inner-sentinel}@<Const> @\exposid{inner_}@;                               // \expos
    constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{inner-sentinel}@<Const> inner);   // \expos

  public:
    @\exposid{sentinel}@() = default;
    constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@<false>, @\exposid{inner-sentinel}@<Const>>;

    template<bool OtherConst>
      requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@<Const>, @\exposid{inner-iterator}@<OtherConst>>
    friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@<Const>, @\exposid{inner-iterator}@<OtherConst>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
      operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

    template<bool OtherConst>
      requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@<Const>, @\exposid{inner-iterator}@<OtherConst>>
    friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
      operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
  };
}
\end{codeblock}

\indexlibraryctor{adjacent_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@<Const> inner);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{inner_} with \tcode{inner}.
\end{itemdescr}

\indexlibraryctor{adjacent_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr @\exposid{sentinel}@(@\exposid{sentinel}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@<false>, @\exposid{inner-sentinel}@<Const>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}.
\end{itemdescr}

\indexlibrarymember{operator==}{adjacent_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@<Const>, @\exposid{inner-iterator}@<OtherConst>>
friend constexpr bool operator==(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};}
\end{itemdescr}

\indexlibrarymember{operator-}{adjacent_transform_view::\exposid{sentinel}}%
\begin{itemdecl}
template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@<Const>, @\exposid{inner-iterator}@<OtherConst>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
  operator-(const @\exposid{iterator}@<OtherConst>& x, const @\exposid{sentinel}@& y);

template<bool OtherConst>
  requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@<Const>, @\exposid{inner-iterator}@<OtherConst>>
friend constexpr range_difference_t<@\exposid{maybe-const}@<OtherConst, @\exposid{InnerView}@>>
  operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@<OtherConst>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};}
\end{itemdescr}

\rSec2[range.chunk]{Chunk view}

\rSec3[range.chunk.overview]{Overview}

\pnum
\tcode{chunk_view} takes a view and a number $N$ and
produces a range of views
that are $N$-sized non-overlapping successive chunks of
the elements of the original view, in order.
The last view in the range can have fewer than $N$ elements.

\pnum
\indexlibrarymember{chunk}{views}%
The name \tcode{views::chunk} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{N},
the expression \tcode{views::chunk(E, N)} is expression-equivalent to
\tcode{chunk_view(E, N)}.

\begin{example}
\begin{codeblock}
vector v = {1, 2, 3, 4, 5};

for (auto r : v | views::chunk(2)) {
  cout << '[';
  auto sep = "";
  for (auto i : r) {
    cout << sep << i;
    sep = ", ";
  }
  cout << "] ";
}
// The above prints \tcode{[1, 2] [3, 4] [5]}
\end{codeblock}
\end{example}

\rSec3[range.chunk.view.input]{Class template \tcode{chunk_view} for input ranges}

\indexlibraryglobal{chunk_view}%
\begin{codeblock}
namespace std::ranges {
  template<class I>
  constexpr I @\exposidnc{div-ceil}@(I num, I denom) {                  // \expos
    I r = num / denom;
    if (num % denom)
      ++r;
    return r;
  }

  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class chunk_view : public view_interface<chunk_view<V>> {
    V @\exposid{base_}@;                                              // \expos
    range_difference_t<V> @\exposid{n_}@;                             // \expos
    range_difference_t<V> @\exposid{remainder_}@ = 0;                 // \expos

    @\exposid{non-propagating-cache}@<iterator_t<V>> @\exposid{current_}@;       // \expos

    // \ref{range.chunk.outer.iter}, class \tcode{chunk_view::\exposid{outer-iterator}}
    class @\exposid{outer-iterator}@;                                 // \expos

    // \ref{range.chunk.inner.iter}, class \tcode{chunk_view::\exposid{inner-iterator}}
    class @\exposid{inner-iterator}@;                                 // \expos

  public:
    constexpr explicit chunk_view(V base, range_difference_t<V> n);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr @\exposid{outer-iterator}@ begin();
    constexpr default_sentinel_t end() const noexcept;

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };

  template<class R>
    chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{chunk_view}%
\begin{itemdecl}
constexpr explicit chunk_view(V base, range_difference_t<V> n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{n > 0} is \tcode{true}.

\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{n_} with \tcode{n}.
\end{itemdescr}

\indexlibrarymember{begin}{chunk_view}%
\begin{itemdecl}
constexpr @\exposid{outer-iterator}@ begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ = ranges::begin(@\exposid{base_}@);
@\exposid{remainder_}@ = @\exposid{n_}@;
return @\exposid{outer-iterator}@(*this);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{chunk_view}%
\begin{itemdecl}
constexpr default_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{default_sentinel}.
\end{itemdescr}

\indexlibrarymember{size}{chunk_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{to-unsigned-like}@(@\exposidnc{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{chunk_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto s = static_cast<range_difference_t<decltype((@\exposidnc{base_}@))>>(ranges::reserve_hint(@\exposidnc{base_}@));
return @\exposidnc{to-unsigned-like}@(@\exposidnc{div-ceil}@(s, @\exposidnc{n_}@));
\end{codeblock}
\end{itemdescr}

\rSec3[range.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}}

\indexlibraryglobal{chunk_view::\exposid{outer-iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class chunk_view<V>::@\exposid{outer-iterator}@ {
    chunk_view* @\exposid{parent_}@;                                        // \expos

    constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent);      // \expos

  public:
    using iterator_concept = input_iterator_tag;
    using difference_type  = range_difference_t<V>;

    // \ref{range.chunk.outer.value}, class \tcode{chunk_view::\exposid{outer-iterator}::value_type}
    struct value_type;

    @\exposid{outer-iterator}@(@\exposid{outer-iterator}@&&) = default;
    @\exposid{outer-iterator}@& operator=(@\exposid{outer-iterator}@&&) = default;

    constexpr value_type operator*() const;
    constexpr @\exposid{outer-iterator}@& operator++();
    constexpr void operator++(int);

    friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t);

    friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
    friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
  };
}
\end{codeblock}

\indexlibraryctor{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibrarymember{operator*}{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr value_type operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this == default_sentinel} is \tcode{false}.

\pnum
\returns
\tcode{value_type(*\exposid{parent_})}.
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr @\exposid{outer-iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this == default_sentinel} is \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::advance(*@\exposid{parent_}@->@\exposid{current_}@, @\exposid{parent_}@->@\exposid{remainder_}@, ranges::end(@\exposid{parent_}@->@\exposid{base_}@));
@\exposid{parent_}@->@\exposid{remainder_}@ = @\exposid{parent_}@->@\exposid{n_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator==}{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return *x.@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && x.@\exposid{parent_}@->@\exposid{remainder_}@ != 0;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
const auto dist = ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@;
if (dist < x.@\exposid{parent_}@->@\exposid{remainder_}@) {
  return dist == 0 ? 0 : 1;
}
return @\exposidnc{div-ceil}@(dist - x.@\exposid{parent_}@->@\exposid{remainder_}@, x.@\exposid{parent_}@->@\exposid{n_}@) + 1;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{outer-iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(y - x);}
\end{itemdescr}

\rSec3[range.chunk.outer.value]{Class \tcode{chunk_view::\exposid{outer-iterator}::value_type}}

\indexlibraryglobal{chunk_view::\exposid{outer-iterator}::value_type}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  struct chunk_view<V>::@\exposid{outer-iterator}@::value_type : view_interface<value_type> {
  private:
    chunk_view* @\exposid{parent_}@;                                        // \expos

    constexpr explicit value_type(chunk_view& parent);          // \expos

  public:
    constexpr @\exposid{inner-iterator}@ begin() const noexcept;
    constexpr default_sentinel_t end() const noexcept;

    constexpr auto size() const
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;

    constexpr auto reserve_hint() const noexcept;
  };
}
\end{codeblock}

\indexlibraryctor{chunk_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr explicit value_type(chunk_view& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibrarymember{begin}{chunk_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr @\exposid{inner-iterator}@ begin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{inner-iterator}(*\exposid{parent_})}.
\end{itemdescr}

\indexlibrarymember{end}{chunk_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr default_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{default_sentinel}.
\end{itemdescr}

\indexlibrarymember{size}{chunk_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr auto size() const
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{to-unsigned-like}@(ranges::min(@\exposid{parent_}@->@\exposid{remainder_}@,
	                            ranges::end(@\exposid{parent_}@->@\exposid{base_}@) - *@\exposid{parent_}@->@\exposid{current_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{chunk_view::\exposid{outer-iterator}::value_type}%
\begin{itemdecl}
constexpr auto reserve_hint() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{to-unsigned-like}@(@\exposid{parent_}@->@\exposid{remainder_}@);
\end{codeblock}
\end{itemdescr}

\rSec3[range.chunk.inner.iter]{Class \tcode{chunk_view::\exposid{inner-iterator}}}

\indexlibraryglobal{chunk_view::\exposid{inner-iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{input_range}@<V>
  class chunk_view<V>::@\exposid{inner-iterator}@ {
    chunk_view* @\exposid{parent_}@;                                                // \expos

    constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept;     // \expos

  public:
    using iterator_concept = input_iterator_tag;
    using difference_type = range_difference_t<V>;
    using value_type = range_value_t<V>;

    @\exposid{inner-iterator}@(@\exposid{inner-iterator}@&&) = default;
    @\exposid{inner-iterator}@& operator=(@\exposid{inner-iterator}@&&) = default;

    constexpr const iterator_t<V>& base() const &;

    constexpr range_reference_t<V> operator*() const;
    constexpr @\exposid{inner-iterator}@& operator++();
    constexpr void operator++(int);

    friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t);

    friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
    friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;

    friend constexpr range_rvalue_reference_t<V> iter_move(const @\exposid{inner-iterator}@& i)
      noexcept(noexcept(ranges::iter_move(*i.@\exposid{parent_}@->@\exposid{current_}@)));

    friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(*x.@\exposid{parent_}@->@\exposid{current_}@, *y.@\exposid{parent_}@->@\exposid{current_}@)))
      requires @\libconcept{indirectly_swappable}@<iterator_t<V>>;
  };
}
\end{codeblock}

\indexlibraryctor{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)}.
\end{itemdescr}

\indexlibrarymember{base}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr const iterator_t<V>& base() const &;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{parent_}->\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator*}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr range_reference_t<V> operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this == default_sentinel} is \tcode{false}.

\pnum
\effects
Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr @\exposid{inner-iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this == default_sentinel} is \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
++*@\exposid{parent_}@->@\exposid{current_}@;
if (*@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@))
  @\exposid{parent_}@->@\exposid{remainder_}@ = 0;
else
  --@\exposid{parent_}@->@\exposid{remainder_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator==}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{parent_}->\exposid{remainder_} == 0}.
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return ranges::min(x.@\exposid{parent_}@->@\exposid{remainder_}@,
                   ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(y - x);}
\end{itemdescr}

\indexlibrarymember{iter_move}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr range_rvalue_reference_t<V> iter_move(const @\exposid{inner-iterator}@& i)
  noexcept(noexcept(ranges::iter_move(*i.@\exposid{parent_}@->@\exposid{current_}@)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::iter_move(*i.\exposid{parent_}->\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{iter_swap}{chunk_view::\exposid{inner-iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(*x.@\exposid{parent_}@->@\exposid{current_}@, *y.@\exposid{parent_}@->@\exposid{current_}@)))
  requires @\libconcept{indirectly_swappable}@<iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{ranges::iter_swap(*x.\exposid{parent_}->\exposid{current_}, *y.\exposid{parent_}->\exposid{current_});}
\end{itemdescr}

\rSec3[range.chunk.view.fwd]{Class template \tcode{chunk_view} for forward ranges}

\indexlibraryglobal{chunk_view}%
\indexlibrarymember{begin}{chunk_view}%
\indexlibrarymember{end}{chunk_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{forward_range}@<V>
  class chunk_view<V> : public view_interface<chunk_view<V>> {
    V @\exposid{base_}@;                            // \expos
    range_difference_t<V> @\exposid{n_}@;           // \expos

    // \ref{range.chunk.fwd.iter}, class template \tcode{chunk_view::\exposid{iterator}}
    template<bool> class @\exposid{iterator}@;      // \expos

  public:
    constexpr explicit chunk_view(V base, range_difference_t<V> n);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>) {
      return @\exposid{iterator}@<false>(this, ranges::begin(@\exposid{base_}@));
    }

    constexpr auto begin() const requires @\libconcept{forward_range}@<const V> {
      return @\exposid{iterator}@<true>(this, ranges::begin(@\exposid{base_}@));
    }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{common_range}@<V> && @\libconcept{sized_range}@<V>) {
        auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@;
        return @\exposid{iterator}@<false>(this, ranges::end(@\exposid{base_}@), missing);
      } else if constexpr (@\libconcept{common_range}@<V> && !@\libconcept{bidirectional_range}@<V>) {
        return @\exposid{iterator}@<false>(this, ranges::end(@\exposid{base_}@));
      } else {
        return default_sentinel;
      }
    }

    constexpr auto end() const requires @\libconcept{forward_range}@<const V> {
      if constexpr (@\libconcept{common_range}@<const V> && @\libconcept{sized_range}@<const V>) {
        auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@;
        return @\exposid{iterator}@<true>(this, ranges::end(@\exposid{base_}@), missing);
      } else if constexpr (@\libconcept{common_range}@<const V> && !@\libconcept{bidirectional_range}@<const V>) {
        return @\exposid{iterator}@<true>(this, ranges::end(@\exposid{base_}@));
      } else {
        return default_sentinel;
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };
}
\end{codeblock}

\indexlibraryctor{chunk_view}%
\begin{itemdecl}
constexpr explicit chunk_view(V base, range_difference_t<V> n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{n > 0} is \tcode{true}.

\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{n_} with \tcode{n}.
\end{itemdescr}

\indexlibrarymember{size}{chunk_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{chunk_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto s = static_cast<range_difference_t<decltype((@\exposid{base_}@))>>(ranges::reserve_hint(@\exposid{base_}@));
return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(s, @\exposid{n_}@));
\end{codeblock}
\end{itemdescr}

\rSec3[range.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges}

\indexlibraryglobal{chunk_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{view}@ V>
    requires @\libconcept{forward_range}@<V>
  template<bool Const>
  class chunk_view<V>::@\exposid{iterator}@ {
    using @\exposid{Parent}@ = @\exposid{maybe-const}@<Const, chunk_view>;                      // \expos
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                                 // \expos

    iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>();                     // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();                         // \expos
    range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0;                                    // \expos
    range_difference_t<@\exposid{Base}@> @\exposid{missing_}@ = 0;                              // \expos

    constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current,       // \expos
                       range_difference_t<@\exposid{Base}@> missing = 0);

  public:
    using iterator_category = input_iterator_tag;
    using iterator_concept = @\seebelow@;
    using value_type = decltype(views::take(subrange(@\exposid{current_}@, @\exposid{end_}@), @\exposid{n_}@));
    using difference_type = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>
                     && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr iterator_t<@\exposid{Base}@> base() const;

    constexpr value_type operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr value_type operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
    friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);

    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> &&
               @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;

    friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \exposid{Base} models \libconcept{random_access_range},
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\end{itemize}

\indexlibraryctor{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current,
                   range_difference_t<@\exposid{Base}@> missing = 0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{current},
\exposid{end_} with \tcode{ranges::end(parent->\exposid{base_})},
\exposid{n_} with \tcode{parent\linebreak ->\exposid{n_}}, and
\exposid{missing_} with \tcode{missing}.
\end{itemdescr}

\indexlibraryctor{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>
                 && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})},
\exposid{end_} with \tcode{std::move(i.\exposid{end_})},
\exposid{n_} with \tcode{i.\exposid{n_}}, and
\exposid{missing_} with \tcode{i.\exposid{missing_}}.
\end{itemdescr}

\indexlibrarymember{base}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{current_}.
\end{itemdescr}

\indexlibrarymember{operator*}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr value_type operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}.

\pnum
\returns
\tcode{views::take(subrange(\exposid{current_}, \exposid{end_}), \exposid{n_})}.
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{n_}@);
@\exposid{missing_}@ = 0;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{x} is positive,
\tcode{ranges::distance(\exposid{current_}, \exposid{end_}) > \exposid{n_} * (x - 1)}
is \tcode{true}.
\begin{note}
If \tcode{x} is negative, the \Fundescx{Effects} paragraph implies a precondition.
\end{note}

\pnum
\effects
Equivalent to:
\begin{codeblock}
if (x > 0) {
  ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * (x - 1));
  @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@);
} else if (x < 0) {
  ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x + @\exposid{missing_}@);
  @\exposid{missing_}@ = 0;
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this += -x;}
\end{itemdescr}

\indexlibrarymember{operator[]}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr value_type operator[](difference_type n) const
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*(*this + n)}.
\end{itemdescr}

\indexlibrarymember{operator-=}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator==}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == x.\exposid{end_}}.
\end{itemdescr}

\indexlibrarymember{operator<}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} < y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator>}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> &&
           @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} <=> y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator+}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r += n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r -= n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{(x.\exposid{current_} - y.\exposid{current_} + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{n_}}.
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}.
\end{itemdescr}

\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(y - x);}
\end{itemdescr}

\rSec2[range.slide]{Slide view}

\rSec3[range.slide.overview]{Overview}

\pnum
\tcode{slide_view} takes a view and a number $N$ and
produces a view
whose $M^\text{th}$ element is a view over
the $M^\text{th}$ through
$(M + N - 1)^\text{th}$ elements
of the original view.
If the original view has fewer than $N$ elements,
the resulting view is empty.

\pnum
\indexlibrarymember{slide}{views}%
The name \tcode{views::slide} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{N},
the expression \tcode{views::slide(E, N)} is expression-equivalent to
\tcode{slide_view(E, N)}.
\begin{example}
\begin{codeblock}
vector v = {1, 2, 3, 4};

for (auto i : v | views::slide(2)) {
  cout << '[' << i[0] << ", " << i[1] << "] ";          // prints \tcode{[1, 2] [2, 3] [3, 4]}
}
\end{codeblock}
\end{example}

\rSec3[range.slide.view]{Class template \tcode{slide_view}}

\indexlibraryglobal{slide_view}%
\indexlibraryctor{slide_view}%
\begin{codeblock}
namespace std::ranges {
  template<class V>
  concept @\defexposconcept{slide-caches-nothing}@ = @\libconcept{random_access_range}@<V> && @\libconcept{sized_range}@<V>;       // \expos

  template<class V>
  concept @\defexposconcept{slide-caches-last}@ =                                            // \expos
    !@\exposconcept{slide-caches-nothing}@<V> && @\libconcept{bidirectional_range}@<V> && @\libconcept{common_range}@<V>;

  template<class V>
  concept @\defexposconcept{slide-caches-first}@ =                                           // \expos
    !@\exposconcept{slide-caches-nothing}@<V> && !@\exposconcept{slide-caches-last}@<V>;

  template<@\libconcept{forward_range}@ V>
    requires @\libconcept{view}@<V>
  class slide_view : public view_interface<slide_view<V>> {
    V @\exposid{base_}@;                            // \expos
    range_difference_t<V> @\exposid{n_}@;           // \expos

    // \ref{range.slide.iterator}, class template \tcode{slide_view::\exposid{iterator}}
    template<bool> class @\exposid{iterator}@;      // \expos

    // \ref{range.slide.sentinel}, class \tcode{slide_view::\exposid{sentinel}}
    class @\exposid{sentinel}@;                     // \expos

  public:
    constexpr explicit slide_view(V base, range_difference_t<V> n);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin()
      requires (!(@\exposconcept{simple-view}@<V> && @\exposconcept{slide-caches-nothing}@<const V>));
    constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@<const V>;

    constexpr auto end()
      requires (!(@\exposconcept{simple-view}@<V> && @\exposconcept{slide-caches-nothing}@<const V>));
    constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@<const V>;

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };

  template<class R>
    slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{slide_view}%
\begin{itemdecl}
constexpr explicit slide_view(V base, range_difference_t<V> n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{n > 0} is \tcode{true}.

\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{n_} with \tcode{n}.
\end{itemdescr}

\indexlibrarymember{begin}{slide_view}%
\begin{itemdecl}
constexpr auto begin()
  requires (!(@\exposconcept{simple-view}@<V> && @\exposconcept{slide-caches-nothing}@<const V>));
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
If \tcode{V} models \exposconcept{slide-caches-first},
\begin{codeblock}
@\exposid{iterator}@<false>(ranges::begin(@\exposid{base_}@),
                ranges::next(ranges::begin(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::end(@\exposid{base_}@)), @\exposid{n_}@)
\end{codeblock}
\item
Otherwise, \tcode{\exposid{iterator}<false>(ranges::begin(\exposid{base_}), \exposid{n_})}.
\end{itemize}

\pnum
\remarks
In order to provide the amortized constant-time complexity
required by the \libconcept{range} concept,
this function caches the result within the \tcode{slide_view}
for use on subsequent calls
when \tcode{V} models \exposconcept{slide-caches-first}.
\end{itemdescr}

\indexlibrarymember{begin}{slide_view}%
\begin{itemdecl}
constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{iterator}<true>(ranges::begin(\exposid{base_}), \exposid{n_})}.
\end{itemdescr}

\indexlibrarymember{end}{slide_view}%
\begin{itemdecl}
constexpr auto end()
  requires (!(@\exposconcept{simple-view}@<V> && @\exposconcept{slide-caches-nothing}@<const V>));
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
If \tcode{V} models \exposconcept{slide-caches-nothing},
\begin{codeblock}
@\exposid{iterator}@<false>(ranges::begin(@\exposid{base_}@) + range_difference_t<V>(size()), @\exposid{n_}@)
\end{codeblock}
\item
Otherwise, if \tcode{V} models \exposconcept{slide-caches-last},
\begin{codeblock}
@\exposid{iterator}@<false>(ranges::prev(ranges::end(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::begin(@\exposid{base_}@)), @\exposid{n_}@)
\end{codeblock}
\item
Otherwise, if \tcode{V} models \libconcept{common_range},
\begin{codeblock}
@\exposid{iterator}@<false>(ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@), @\exposid{n_}@)
\end{codeblock}
\item
Otherwise, \tcode{\exposid{sentinel}(ranges::end(\exposid{base_}))}.
\end{itemize}

\pnum
\remarks
In order to provide the amortized constant-time complexity
required by the \libconcept{range} concept,
this function caches the result within the \tcode{slide_view}
for use on subsequent calls
when \tcode{V} models \exposconcept{slide-caches-last}.
\end{itemdescr}

\indexlibrarymember{end}{slide_view}%
\begin{itemdecl}
constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{begin() + range_difference_t<const V>(size())}.
\end{itemdescr}

\indexlibrarymember{size}{slide_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto sz = ranges::distance(@\exposid{base_}@) - @\exposid{n_}@ + 1;
if (sz < 0) sz = 0;
return @\exposid{to-unsigned-like}@(sz);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{slide_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto sz = static_cast<range_difference_t<decltype((@\exposid{base_}@))>>(ranges::reserve_hint(@\exposid{base_}@)) -
                                                             @\exposid{n_}@ + 1;
if (sz < 0) sz = 0;
return @\exposid{to-unsigned-like}@(sz);
\end{codeblock}
\end{itemdescr}

\rSec3[range.slide.iterator]{Class template \tcode{slide_view::\exposid{iterator}}}

\indexlibraryglobal{slide_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V>
    requires @\libconcept{view}@<V>
  template<bool Const>
  class slide_view<V>::@\exposid{iterator}@ {
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                 // \expos
    iterator_t<@\exposid{Base}@> @\exposid{current_}@   = iterator_t<@\exposid{Base}@>();   // \expos
    iterator_t<@\exposid{Base}@> @\exposid{last_ele_}@  = iterator_t<@\exposid{Base}@>();   // \expos,
                                               // present only if \exposid{Base} models \tcode{\exposconcept{slide-caches-first}}
    range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0;                    // \expos

    constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) // \expos
      requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>);

    constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele,  // \expos
                       range_difference_t<@\exposid{Base}@> n)
      requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>;

  public:
    using iterator_category = input_iterator_tag;
    using iterator_concept = @\seebelow@;
    using value_type = decltype(views::counted(@\exposid{current_}@, @\exposid{n_}@));
    using difference_type = range_difference_t<@\exposid{Base}@>;

    @\exposid{iterator}@() = default;
    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr auto operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr auto operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);

    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> &&
               @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \exposid{Base} models \libconcept{random_access_range},
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\end{itemize}

\pnum
If the invocation of any non-const member function of \exposid{iterator}
exits via an exception, the \exposid{iterator} acquires a singular value.

\indexlibraryctor{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n)
  requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{current} and
\exposid{n_} with \tcode{n}.
\end{itemdescr}

\indexlibraryctor{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele,
                   range_difference_t<@\exposid{Base}@> n)
  requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{current},
\exposid{last_ele_} with \tcode{last_ele}, and
\exposid{n_} with \tcode{n}.
\end{itemdescr}

\indexlibraryctor{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and
\exposid{n_} with \tcode{i.\exposid{n_}}.
\begin{note}
\tcode{\exposid{iterator}<true>} can only be formed
when \exposid{Base} models \exposconcept{slide-caches-nothing},
in which case \exposid{last_ele_} is not present.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator*}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{views::counted(\exposid{current_}, \exposid{n_})}.
\end{itemdescr}

\indexlibrarymember{operator++}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\exposid{current_} and \exposid{last_ele_} (if present) are incrementable.

\pnum
\ensures
\exposid{current_} and \exposid{last_ele_} (if present) are
each equal to \tcode{ranges::next(i)},
where \tcode{i} is the value of that data member before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\exposid{current_} and \exposid{last_ele_} (if present) are decrementable.

\pnum
\ensures
\exposid{current_} and \exposid{last_ele_} (if present) are
each equal to \tcode{ranges::prev(i)},
where \tcode{i} is the value of that data member before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator--}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_} + x} and \tcode{\exposid{last_ele_} + x} (if \exposid{last_ele_} is present)
have well-defined behavior.

\pnum
\ensures
\exposid{current_} and \exposid{last_ele_} (if present) are
each equal to \tcode{i + x},
where \tcode{i} is the value of that data member before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator-=}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_} - x} and \tcode{\exposid{last_ele_} - x} (if \exposid{last_ele_} is present)
have well-defined behavior.

\pnum
\ensures
\exposid{current_} and \exposid{last_ele_} (if present) are
each equal to \tcode{i - x},
where \tcode{i} is the value of that data member before the call.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator[]}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator[](difference_type n) const
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});}
\end{itemdescr}

\indexlibrarymember{operator==}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If \exposid{last_ele_} is present,
\tcode{x.\exposid{last_ele_} == y.\exposid{last_ele_}};
otherwise, \tcode{x.\exposid{current_} == y.\exposid{cur\-rent_}}.
\end{itemdescr}

\indexlibrarymember{operator<}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} < y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator>}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> &&
           @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} <=> y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator+}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r += n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r -= n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{slide_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If \exposid{last_ele_} is present,
\tcode{x.\exposid{last_ele_} - y.\exposid{last_ele_}};
otherwise, \tcode{x.\exposid{current_} - y.\exposid{cur\-rent_}}.
\end{itemdescr}

\rSec3[range.slide.sentinel]{Class \tcode{slide_view::\exposid{sentinel}}}

\indexlibraryglobal{slide_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V>
    requires @\libconcept{view}@<V>
  class slide_view<V>::@\exposid{sentinel}@ {
    sentinel_t<V> @\exposid{end_}@ = sentinel_t<V>();             // \expos
    constexpr explicit @\exposid{sentinel}@(sentinel_t<V> end);   // \expos

  public:
    @\exposid{sentinel}@() = default;

    friend constexpr bool operator==(const @\exposid{iterator}@<false>& x, const @\exposid{sentinel}@& y);

    friend constexpr range_difference_t<V>
      operator-(const @\exposid{iterator}@<false>& x, const @\exposid{sentinel}@& y)
        requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;

    friend constexpr range_difference_t<V>
      operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<false>& x)
        requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
  };
}
\end{codeblock}

\pnum
\begin{note}
\exposid{sentinel} is used
only when \tcode{\exposconcept{slide-caches-first}<V>} is \tcode{true}.
\end{note}

\indexlibraryctor{slide_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(sentinel_t<V> end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{end}.
\end{itemdescr}

\indexlibrarymember{operator==}{slide_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@<false>& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{last_ele_} == y.\exposid{end_}}.
\end{itemdescr}

\indexlibrarymember{operator-}{slide_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr range_difference_t<V>
  operator-(const @\exposid{iterator}@<false>& x, const @\exposid{sentinel}@& y)
    requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}.
\end{itemdescr}

\indexlibrarymember{operator-}{slide_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr range_difference_t<V>
  operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@<false>& x)
    requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{y.\exposid{end_} - x.\exposid{last_ele_}}.
\end{itemdescr}

\rSec2[range.chunk.by]{Chunk by view}

\rSec3[range.chunk.by.overview]{Overview}

\pnum
\tcode{chunk_by_view} takes a view and a predicate, and
splits the view into \tcode{subrange}s
between each pair of adjacent elements
for which the predicate returns \tcode{false}.

\pnum
\indexlibrarymember{chunk_by}{views}%
The name \tcode{views::chunk_by} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{F},
the expression \tcode{views::chunk_by(E, F)} is expression-equivalent to
\tcode{chunk_by_view(E, F)}.
\begin{example}
\begin{codeblock}
vector v = {1, 2, 2, 3, 0, 4, 5, 2};

for (auto r : v | views::chunk_by(ranges::less_equal{})) {
  cout << '[';
  auto sep = "";
  for (auto i : r) {
    cout << sep << i;
    sep = ", ";
  }
  cout << "] ";
}
// The above prints \tcode{[1, 2, 2, 3] [0, 4, 5] [2]}
\end{codeblock}
\end{example}

\rSec3[range.chunk.by.view]{Class template \tcode{chunk_by_view}}

\indexlibraryglobal{chunk_by_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@<iterator_t<V>, iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> {
    V @\exposid{base_}@ = V();                                          // \expos
    @\exposidnc{movable-box}@<Pred> @\exposid{pred_}@;                                // \expos

    // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}}
    class @\exposidnc{iterator}@;                                         // \expos

  public:
    chunk_by_view() requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pred> = default;
    constexpr explicit chunk_by_view(V base, Pred pred);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr const Pred& pred() const;

    constexpr @\exposid{iterator}@ begin();
    constexpr auto end();

    constexpr iterator_t<V> @\exposidnc{find-next}@(iterator_t<V>);       // \expos
    constexpr iterator_t<V> @\exposidnc{find-prev}@(iterator_t<V>)        // \expos
      requires @\libconcept{bidirectional_range}@<V>;
  };

  template<class R, class Pred>
    chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, Pred>;
}
\end{codeblock}

\indexlibraryctor{chunk_by_view}%
\begin{itemdecl}
constexpr explicit chunk_by_view(V base, Pred pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{pred_} with \tcode{std::move(pred)}.
\end{itemdescr}

\indexlibrarymember{pred}{chunk_by_view}%
\begin{itemdecl}
constexpr const Pred& pred() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *\exposid{pred_};}
\end{itemdescr}

\indexlibrarymember{begin}{chunk_by_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{pred_}.has_value()} is \tcode{true}.

\pnum
\returns
\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}.

\pnum
\remarks
In order to provide
the amortized constant-time complexity required by the \libconcept{range} concept,
this function caches the result within the \tcode{chunk_by_view}
for use on subsequent calls.
\end{itemdescr}

\indexlibrarymember{end}{chunk_by_view}%
\begin{itemdecl}
constexpr auto end();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (@\libconcept{common_range}@<V>) {
  return @\exposid{iterator}@(*this, ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@));
} else {
  return default_sentinel;
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{find-next}}{chunk_by_view}%
\begin{itemdecl}
constexpr iterator_t<V> @\exposid{find-next}@(iterator_t<V> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{pred_}.has_value()} is \tcode{true}.

\pnum
\returns
\begin{codeblock}
ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))),
             1, ranges::end(@\exposid{base_}@))
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{find-prev}}{chunk_by_view}%
\begin{itemdecl}
constexpr iterator_t<V> @\exposid{find-prev}@(iterator_t<V> current) requires @\libconcept{bidirectional_range}@<V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}.
\item
\tcode{\exposid{pred_}.has_value()} is \tcode{true}.
\end{itemize}

\pnum
\returns
An iterator \tcode{i}
in the range \range{ranges::begin(\exposid{base_})}{current} such that:
\begin{itemize}
\item
\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and
\item
if \tcode{i} is not equal to \tcode{ranges::begin(\exposid{base_})},
then \tcode{bool(invoke(*\exposid{pred_}, *ranges::prev(i), *i))}
is \tcode{false}.
\end{itemize}
\end{itemdescr}

\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}}

\indexlibraryglobal{chunk_by_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@<iterator_t<V>, iterator_t<V>> Pred>
    requires @\libconcept{view}@<V> && is_object_v<Pred>
  class chunk_by_view<V, Pred>::@\exposid{iterator}@ {
    chunk_by_view* @\exposid{parent_}@ = nullptr;                                   // \expos
    iterator_t<V> @\exposid{current_}@ = iterator_t<V>();                           // \expos
    iterator_t<V> @\exposid{next_}@    = iterator_t<V>();                           // \expos

    constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t<V> current,    // \expos
                       iterator_t<V> next);

  public:
    using value_type = subrange<iterator_t<V>>;
    using difference_type  = range_difference_t<V>;
    using iterator_category = input_iterator_tag;
    using iterator_concept = @\seebelow@;

    @\exposid{iterator}@() = default;

    constexpr value_type operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr @\exposid{iterator}@ operator++(int);

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<V>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<V>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
    friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \tcode{V} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\end{itemize}

\indexlibraryctor{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t<V> current, iterator_t<V> next);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{parent_} with \tcode{addressof(parent)},
\exposid{current_} with \tcode{current}, and
\exposid{next_} with \tcode{next}.
\end{itemdescr}

\indexlibrarymember{operator*}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr value_type operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\exposid{current_} is not equal to \exposid{next_}.

\pnum
\returns
\tcode{subrange(\exposid{current_}, \exposid{next_})}.
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\exposid{current_} is not equal to \exposid{next_}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{current_}@ = @\exposid{next_}@;
@\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{current_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{next_}@ = @\exposid{current_}@;
@\exposid{current_}@ = @\exposid{parent_}@->@\exposid{find-prev}@(@\exposid{next_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator==}{chunk_by_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == x.\exposid{next_}}.
\end{itemdescr}

\rSec2[range.stride]{Stride view}

\rSec3[range.stride.overview]{Overview}

\pnum
\tcode{stride_view} presents a view of an underlying sequence,
advancing over $n$ elements at a time,
as opposed to the usual single-step succession.

\pnum
The name \tcode{views::stride} denotes
a range adaptor object\iref{range.adaptor.object}.
Given subexpressions \tcode{E} and \tcode{N},
the expression \tcode{views::stride(E, N)}
is expression-equivalent to \tcode{stride_view(E, N)}.

\pnum
\begin{example}
\begin{codeblock}
auto input = views::iota(0, 12) | views::stride(3);
ranges::copy(input, ostream_iterator<int>(cout, " "));                  // prints \tcode{0 3 6 9}
ranges::copy(input | views::reverse, ostream_iterator<int>(cout, " ")); // prints \tcode{9 6 3 0}
\end{codeblock}
\end{example}

\rSec3[range.stride.view]{Class template \tcode{stride_view}}

\indexlibraryglobal{stride_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class stride_view : public view_interface<stride_view<V>> {
    V @\exposid{base_}@;                                    // \expos
    range_difference_t<V> @\exposid{stride_}@;              // \expos
    // \ref{range.stride.iterator}, class template \tcode{stride_view::\exposid{iterator}}
    template<bool> class @\exposid{iterator}@;              // \expos
  public:
    constexpr explicit stride_view(V base, range_difference_t<V> stride);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr range_difference_t<V> stride() const noexcept;

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>) {
      return @\exposid{iterator}@<false>(this, ranges::begin(@\exposid{base_}@));
    }

    constexpr auto begin() const requires @\libconcept{range}@<const V> {
      return @\exposid{iterator}@<true>(this, ranges::begin(@\exposid{base_}@));
    }

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>) {
      if constexpr (@\libconcept{common_range}@<V> && @\libconcept{sized_range}@<V> && @\libconcept{forward_range}@<V>) {
        auto missing = (@\exposid{stride_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{stride_}@) % @\exposid{stride_}@;
        return @\exposid{iterator}@<false>(this, ranges::end(@\exposid{base_}@), missing);
      } else if constexpr (@\libconcept{common_range}@<V> && !@\libconcept{bidirectional_range}@<V>) {
        return @\exposid{iterator}@<false>(this, ranges::end(@\exposid{base_}@));
      } else {
        return default_sentinel;
      }
    }

    constexpr auto end() const requires @\libconcept{range}@<const V> {
      if constexpr (@\libconcept{common_range}@<const V> && @\libconcept{sized_range}@<const V> && @\libconcept{forward_range}@<const V>) {
        auto missing = (@\exposid{stride_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{stride_}@) % @\exposid{stride_}@;
        return @\exposid{iterator}@<true>(this, ranges::end(@\exposid{base_}@), missing);
      } else if constexpr (@\libconcept{common_range}@<const V> && !@\libconcept{bidirectional_range}@<const V>) {
        return @\exposid{iterator}@<true>(this, ranges::end(@\exposid{base_}@));
      } else {
        return default_sentinel;
      }
    }

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };

  template<class R>
    stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{stride_view}%
\begin{itemdecl}
constexpr stride_view(V base, range_difference_t<V> stride);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{stride > 0} is \tcode{true}.

\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)} and
\exposid{stride_} with \tcode{stride}.
\end{itemdescr}

\indexlibrarymember{stride}{stride_view}%
\begin{itemdecl}
constexpr range_difference_t<V> stride() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{stride_}.
\end{itemdescr}

\indexlibrarymember{size}{stride_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{stride_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{stride_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto s = static_cast<range_difference_t<decltype((@\exposid{base_}@))>>(ranges::reserve_hint(@\exposid{base_}@));
return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(s, @\exposid{stride_}@));
\end{codeblock}
\end{itemdescr}

\rSec3[range.stride.iterator]{Class template \tcode{stride_view::\exposid{iterator}}}

\indexlibraryglobal{stride_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  template<bool Const>
  class stride_view<V>::@\exposid{iterator}@ {
    using @\exposid{Parent}@ = @\exposid{maybe-const}@<Const, stride_view>;                      // \expos
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                                  // \expos

    iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>();                      // \expos
    sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>();                          // \expos
    range_difference_t<@\exposid{Base}@> @\exposid{stride_}@ = 0;                                // \expos
    range_difference_t<@\exposid{Base}@> @\exposid{missing_}@ = 0;                               // \expos

    constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current,        // \expos
                       range_difference_t<@\exposid{Base}@> missing = 0);
  public:
    using difference_type = range_difference_t<@\exposid{Base}@>;
    using value_type = range_value_t<@\exposid{Base}@>;
    using iterator_concept = @\seebelow@;
    using iterator_category = @\seebelow@;    // not always present

    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposid{Base}@>> = default;

    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> other)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>
                     && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;

    constexpr iterator_t<@\exposid{Base}@> base() &&;
    constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;

    constexpr decltype(auto) operator*() const { return *@\exposid{current_}@; }

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;

    constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    constexpr @\exposid{iterator}@& operator-=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    constexpr decltype(auto) operator[](difference_type n) const
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>
    { return *(*this + n); }

    friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;

    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& x)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type n)
      requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;

    friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;

    friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
      noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));

    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
      requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \exposid{Base} models \libconcept{random_access_range},
then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{bidirectional_range},
then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise, if \exposid{Base} models \libconcept{forward_range},
then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
The member \grammarterm{typedef-name} \tcode{iterator_category} is declared
if and only if \exposid{Base} models \libconcept{forward_range}.
In that case,
\tcode{\exposid{iterator}::iterator_category} is defined as follows:
\begin{itemize}
\item
Let \tcode{C} denote
the type \tcode{iterator_traits<iterator_t<\exposid{Base}>>::iterator_category}.
\item
If \tcode{C} models
\tcode{\libconcept{derived_from}<random_access_iterator_tag>},
then \tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}.
\item
Otherwise, \tcode{iterator_category} denotes \tcode{C}.
\end{itemize}

\indexlibraryctor{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current,
                   range_difference_t<@\exposid{Base}@> missing = 0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)},
\exposid{end_} with \tcode{ranges::end(parent->\exposid{base_})},
\exposid{stride_} with \tcode{parent->\exposid{stride_}}, and
\exposid{missing_} with \tcode{missing}.
\end{itemdescr}

\indexlibraryctor{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>
                 && @\libconcept{convertible_to}@<sentinel_t<V>, sentinel_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})},
\exposid{end_} with \tcode{std::move(i.\exposid{end_})},
\exposid{stride_} with \tcode{i.\exposid{stride_}}, and
\exposid{missing_} with \tcode{i.\exposid{missing_}}.
\end{itemdescr}

\indexlibrarymember{base}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{std::move(\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{base}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{current_}.
\end{itemdescr}

\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@, @\exposid{end_}@);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this;}
\end{itemdescr}

\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{stride_}@);
@\exposid{missing_}@ = 0;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{n} is positive,
\tcode{ranges::distance(\exposid{current_}, \exposid{end_}) > \exposid{stride_} * (n - 1)}
is \tcode{true}.
\begin{note}
If \tcode{n} is negative, the \Fundescx{Effects} paragraph implies a precondition.
\end{note}

\pnum
\effects
Equivalent to:
\begin{codeblock}
if (n > 0) {
  ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * (n - 1));
  @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@, @\exposid{end_}@);
} else if (n < 0) {
  ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * n + @\exposid{missing_}@);
  @\exposid{missing_}@ = 0;
}
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-=}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this += -x;}
\end{itemdescr}

\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == x.\exposid{end_}}.
\end{itemdescr}

\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator<}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} < y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator>}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y < x;}
\end{itemdescr}

\indexlibrarymember{operator<=}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(y < x);}
\end{itemdescr}

\indexlibrarymember{operator>=}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !(x < y);}
\end{itemdescr}

\indexlibrarymember{operator<=>}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} <=> y.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator+}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r += n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n)
  requires @\libconcept{random_access_range}@<@\exposid{Base}@>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto r = i;
r -= n;
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
Let \tcode{N} be \tcode{(x.\exposid{current_} - y.\exposid{current_})}.
\begin{itemize}
\item
If \exposid{Base} models \libconcept{forward_range},
\tcode{(N + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{stride_}}.
\item
Otherwise, if \tcode{N} is negative, \tcode{-\exposid{div-ceil}(-N, x.\exposid{stride_})}.
\item
Otherwise, \tcode{\exposid{div-ceil}(N, x.\exposid{stride_})}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{stride_})}.
\end{itemdescr}

\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(y - x);}
\end{itemdescr}

\indexlibrarymember{iter_move}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
  noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{iter_swap}{stride_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
  requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});}
\end{itemdescr}

\rSec2[range.cartesian]{Cartesian product view}

\rSec3[range.cartesian.overview]{Overview}

\indexlibraryglobal{cartesian_product_view}%
\pnum
\tcode{cartesian_product_view} takes any non-zero number of ranges $n$ and
produces a view of tuples calculated by
the $n$-ary cartesian product of the provided ranges.

\pnum
The name \tcode{views::cartesian_product} denotes a customization point object\iref{customization.point.object}.
Given a pack of subexpressions \tcode{Es},
the expression \tcode{views::cartesian_product(Es...)}
is expression-equivalent to
\begin{itemize}
\item
\tcode{views::single(tuple())}
if \tcode{Es} is an empty pack,
\item
otherwise,
\tcode{cartesian_product_view<views::all_t<decltype((Es))>...>(Es...)}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
vector<int> v { 0, 1, 2 };
for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) {
  cout << a << ' ' << b << ' ' << c << '\n';
}
// The above prints
// \tcode{0 0 0}
// \tcode{0 0 1}
// \tcode{0 0 2}
// \tcode{0 1 0}
// \tcode{0 1 1}
// ...
\end{codeblock}
\end{example}

\rSec3[range.cartesian.view]{Class template \tcode{cartesian_product_view}}

\indexlibraryglobal{cartesian_product_view}%
\begin{codeblock}
namespace std::ranges {
  template<bool Const, class First, class... Vs>
  concept @\defexposconcept{cartesian-product-is-random-access}@ =          // \expos
    (@\libconcept{random_access_range}@<@\exposid{maybe-const}@<Const, First>> && ... &&
      (@\libconcept{random_access_range}@<@\exposid{maybe-const}@<Const, Vs>>
        && @\libconcept{sized_range}@<@\exposid{maybe-const}@<Const, Vs>>));

  template<class R>
  concept @\defexposconcept{cartesian-product-common-arg}@ =                // \expos
    @\libconcept{common_range}@<R> || (@\libconcept{sized_range}@<R> && @\libconcept{random_access_range}@<R>);

  template<bool Const, class First, class... Vs>
  concept @\defexposconcept{cartesian-product-is-bidirectional}@ =          // \expos
    (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@<Const, First>> && ... &&
      (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@<Const, Vs>>
        && @\exposconcept{cartesian-product-common-arg}@<@\exposid{maybe-const}@<Const, Vs>>));

  template<class First, class...>
  concept @\defexposconcept{cartesian-product-is-common}@ =                 // \expos
    @\exposconcept{cartesian-product-common-arg}@<First>;

  template<class... Vs>
  concept @\defexposconcept{cartesian-product-is-sized}@ =                  // \expos
    (@\libconcept{sized_range}@<Vs> && ...);

  template<bool Const, template<class> class FirstSent, class First, class... Vs>
    concept @\defexposconcept{cartesian-is-sized-sentinel}@ =               // \expos
      (@\libconcept{sized_sentinel_for}@<FirstSent<@\exposid{maybe-const}@<Const, First>>,
          iterator_t<@\exposid{maybe-const}@<Const, First>>> && ...
        && (@\libconcept{sized_range}@<@\exposid{maybe-const}@<Const, Vs>>
          && @\libconcept{sized_sentinel_for}@<iterator_t<@\exposid{maybe-const}@<Const, Vs>>,
              iterator_t<@\exposid{maybe-const}@<Const, Vs>>>));

  template<@\exposconcept{cartesian-product-common-arg}@ R>
  constexpr auto @\exposid{cartesian-common-arg-end}@(R& r) {       // \expos
    if constexpr (@\libconcept{common_range}@<R>) {
      return ranges::end(r);
    } else {
      return ranges::begin(r) + ranges::distance(r);
    }
  }

  template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs>
    requires (@\libconcept{view}@<First> && ... && @\libconcept{view}@<Vs>)
  class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {
  private:
    tuple<First, Vs...> @\exposid{bases_}@;                 // \expos
    // \ref{range.cartesian.iterator}, class template \tcode{cartesian_product_view::\exposid{iterator}}
    template<bool Const> class @\exposid{iterator}@;       // \expos

  public:
    constexpr cartesian_product_view() = default;
    constexpr explicit cartesian_product_view(First first_base, Vs... bases);

    constexpr @\exposid{iterator}@<false> begin()
      requires (!@\exposconcept{simple-view}@<First> || ... || !@\exposconcept{simple-view}@<Vs>);
    constexpr @\exposid{iterator}@<true> begin() const
      requires (@\libconcept{range}@<const First> && ... && @\libconcept{range}@<const Vs>);

    constexpr @\exposid{iterator}@<false> end()
      requires ((!@\exposconcept{simple-view}@<First> || ... || !@\exposconcept{simple-view}@<Vs>) &&
        @\exposconcept{cartesian-product-is-common}@<First, Vs...>);
    constexpr @\exposid{iterator}@<true> end() const
      requires @\exposconcept{cartesian-product-is-common}@<const First, const Vs...>;
    constexpr default_sentinel_t end() const noexcept;

    constexpr @\seebelow@ size()
      requires @\exposconcept{cartesian-product-is-sized}@<First, Vs...>;
    constexpr @\seebelow@ size() const
      requires @\exposconcept{cartesian-product-is-sized}@<const First, const Vs...>;
  };

  template<class... Vs>
    cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>;
}
\end{codeblock}

\indexlibraryctor{cartesian_product_view}%
\begin{itemdecl}
constexpr explicit cartesian_product_view(First first_base, Vs... bases);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{bases_}
with \tcode{std::move(first_base), std::move(bases)...}.
\end{itemdescr}

\indexlibrarymember{begin}{cartesian_product_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<false> begin()
  requires (!@\exposconcept{simple-view}@<First> || ... || !@\exposconcept{simple-view}@<Vs>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{iterator}@<false>(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{begin}{cartesian_product_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<true> begin() const
  requires (@\libconcept{range}@<const First> && ... && @\libconcept{range}@<const Vs>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{iterator}@<true>(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{cartesian_product_view}%
\begin{itemdecl}
constexpr @\exposid{iterator}@<false> end()
  requires ((!@\exposconcept{simple-view}@<First> || ... || !@\exposconcept{simple-view}@<Vs>)
    && @\exposconcept{cartesian-product-is-common}@<First, Vs...>);
constexpr @\exposid{iterator}@<true> end() const
  requires @\exposconcept{cartesian-product-is-common}@<const First, const Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let:
\begin{itemize}
\item
\exposid{is-const} be \tcode{true} for the const-qualified overload, and
\tcode{false} otherwise;
\item
\exposid{is-empty} be \tcode{true}
if the expression \tcode{ranges::empty(rng)} is \tcode{true}
for any \tcode{rng} among the underlying ranges except the first one and
\tcode{false} otherwise; and
\item
\tcode{\exposid{begin-or-first-end}(rng)} be expression-equivalent to
\tcode{\exposid{is-empty} ? ranges::begin(rng) : \brk{}\exposid{cartesian-common-arg-end}(rng)}
if \tcode{rng} is the first underlying range and
\tcode{ranges::begin(rng)} otherwise.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{iterator}@<@\exposid{is-const}@> it(*this, @\exposid{tuple-transform}@(
  [](auto& rng){ return @\exposid{begin-or-first-end}@(rng); }, @\exposid{bases_}@));
return it;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{end}{cartesian_product_view}%
\begin{itemdecl}
constexpr default_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{default_sentinel}.
\end{itemdescr}

\indexlibrarymember{size}{cartesian_product_view}%
\begin{itemdecl}
constexpr @\seebelow@ size()
  requires @\exposconcept{cartesian-product-is-sized}@<First, Vs...>;
constexpr @\seebelow@ size() const
  requires @\exposconcept{cartesian-product-is-sized}@<const First, const Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
The return type is an \impldef{return type of \tcode{cartesian_product_view::size}} unsigned-integer-like type.

\pnum
\recommended
The return type should be the smallest unsigned-integer-like type
that is sufficiently wide to store the product of the maximum sizes of
all the underlying ranges, if such a type exists.

\pnum
Let $p$ be the product of the sizes of all the ranges in \exposid{bases_}.

\pnum
\expects
$p$ can be represented by the return type.

\pnum
\returns
$p$.
\end{itemdescr}

\rSec3[range.cartesian.iterator]{Class template \tcode{cartesian_product_view::\exposid{iterator}}}

\indexlibraryglobal{cartesian_product_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs>
    requires (@\libconcept{view}@<First> && ... && @\libconcept{view}@<Vs>)
  template<bool Const>
  class cartesian_product_view<First, Vs...>::@\exposid{iterator}@ {
  public:
    using iterator_category = input_iterator_tag;
    using iterator_concept  = @\seebelow@;
    using value_type = tuple<range_value_t<@\exposid{maybe-const}@<Const, First>>,
      range_value_t<@\exposid{maybe-const}@<Const, Vs>>...>;
    using reference = tuple<range_reference_t<@\exposid{maybe-const}@<Const, First>>,
      range_reference_t<@\exposid{maybe-const}@<Const, Vs>>...>;
    using difference_type = @\seebelow@;

    @\exposid{iterator}@() = default;

    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i) requires Const &&
      (@\libconcept{convertible_to}@<iterator_t<First>, iterator_t<const First>> &&
        ... && @\libconcept{convertible_to}@<iterator_t<Vs>, iterator_t<const Vs>>);

    constexpr auto operator*() const;
    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);
    constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@<Const, First>>;

    constexpr @\exposid{iterator}@& operator--()
      requires @\exposconcept{cartesian-product-is-bidirectional}@<Const, First, Vs...>;
    constexpr @\exposid{iterator}@ operator--(int)
      requires @\exposconcept{cartesian-product-is-bidirectional}@<Const, First, Vs...>;

    constexpr @\exposid{iterator}@& operator+=(difference_type x)
      requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
    constexpr @\exposid{iterator}@& operator-=(difference_type x)
      requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;

    constexpr reference operator[](difference_type n) const
      requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, First>>>;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);

    friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{all-random-access}@<Const, First, Vs...>;

    friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y)
      requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
    friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y)
      requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
    friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y)
      requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      requires @\exposconcept{cartesian-is-sized-sentinel}@<Const, iterator_t, First, Vs...>;

    friend constexpr difference_type operator-(const @\exposid{iterator}@& i, default_sentinel_t)
      requires @\exposconcept{cartesian-is-sized-sentinel}@<Const, sentinel_t, First, Vs...>;
    friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& i)
      requires @\exposconcept{cartesian-is-sized-sentinel}@<Const, sentinel_t, First, Vs...>;

    friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@);

    friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@)
      requires (@\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, First>>> && ... &&
        @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, Vs>>>);

  private:
    using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@<Const, cartesian_product_view>;          // \expos
    @\exposidnc{Parent}@* @\exposidnc{parent_}@ = nullptr;                                          // \expos
    tuple<iterator_t<@\exposid{maybe-const}@<Const, First>>,
      iterator_t<@\exposidnc{maybe-const}@<Const, Vs>>...> @\exposidnc{current_}@;                  // \expos

    template<size_t N = sizeof...(Vs)>
      constexpr void @\exposidnc{next}@();                                            // \expos

    template<size_t N = sizeof...(Vs)>
      constexpr void @\exposidnc{prev}@();                                            // \expos

    template<class Tuple>
      constexpr difference_type @\exposidnc{distance-from}@(const Tuple& t) const;    // \expos

    constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, tuple<iterator_t<@\exposid{maybe-const}@<Const, First>>,
      iterator_t<@\exposidnc{maybe-const}@<Const, Vs>>...> current);                  // \expos
  };
}
\end{codeblock}

\pnum
\tcode{\exposid{iterator}::iterator_concept} is defined as follows:
\begin{itemize}
\item
If \tcode{\exposconcept{cartesian-product-is-random-access}<Const, First, Vs...>}
is modeled,
then \tcode{iterator_con\-cept} denotes \tcode{random_access_iterator_tag}.
\item
Otherwise,
if \tcode{\exposconcept{cartesian-product-is-bidirectional}<Const, First, Vs...>}
is modeled,
then \tcode{it\-erator_concept} denotes \tcode{bidirectional_iterator_tag}.
\item
Otherwise,
if \tcode{\exposid{maybe-const}<Const, First>} models \libconcept{forward_range},
then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}.
\item
Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}.
\end{itemize}

\pnum
\tcode{\exposid{iterator}::difference_type} is
an \impldef{type of \tcode{ranges::cartesian_product_view::\exposid{iterator}::difference_type}}
signed-integer-like type.

\pnum
\recommended
\tcode{\exposid{iterator}::difference_type} should be
the smallest signed-integer-like type
that is sufficiently wide to store
the product of the maximum sizes of all underlying ranges
if such a type exists.

\indexlibrarymember{\exposid{next}}{cartesian_product_view}%
\begin{itemdecl}
template<size_t N = sizeof...(Vs)>
  constexpr void @\exposid{next}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto& it = std::get<N>(@\exposid{current_}@);
++it;
if constexpr (N > 0) {
  if (it == ranges::end(std::get<N>(@\exposid{parent_}@->@\exposid{bases_}@))) {
    it = ranges::begin(std::get<N>(@\exposid{parent_}@->@\exposid{bases_}@));
    @\exposid{next}@<N - 1>();
  }
}
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{prev}}{cartesian_product_view}%
\begin{itemdecl}
template<size_t N = sizeof...(Vs)>
  constexpr void @\exposid{prev}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto& it = std::get<N>(@\exposid{current_}@);
if constexpr (N > 0) {
  if (it == ranges::begin(std::get<N>(@\exposid{parent_}@->@\exposid{bases_}@))) {
    it = @\exposid{cartesian-common-arg-end}@(std::get<N>(@\exposid{parent_}@->@\exposid{bases_}@));
    @\exposid{prev}@<N - 1>();
  }
}
--it;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{\exposid{distance-from}}{cartesian_product_view}%
\begin{itemdecl}
template<class Tuple>
  constexpr difference_type @\exposid{distance-from}@(const Tuple& t) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let:
\begin{itemize}
\item
$\exposid{scaled-size}(N)$ be the product of
\tcode{static_cast<difference_type>(ranges::size(std::get<\brk{}$N$>(\exposid{parent_}->\exposid{bases_})))} and
$\exposid{scaled-size}(N+1)$
if $N \le \tcode{sizeof...(Vs)}$, otherwise \tcode{static_cast<difference_type>(1)};
\item
$\exposid{scaled-distance}(N)$ be the product of
\tcode{static_cast<difference_type>(std::get<$N$>(\exposid{cur\-rent_}) - std::get<$N$>(t))} and $\exposid{scaled-size}(N+1)$; and
\item
\exposid{scaled-sum} be the sum of $\exposid{scaled-distance}(N)$
for every integer $0 \le N \le \tcode{sizeof...(Vs)}$.
\end{itemize}

\pnum
\expects
\exposid{scaled-sum} can be represented by \tcode{difference_type}.

\pnum
\returns
\exposid{scaled-sum}.
\end{itemdescr}

\indexlibraryctor{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, tuple<iterator_t<@\exposid{maybe-const}@<Const, First>>,
  iterator_t<@\exposid{maybe-const}@<Const, Vs>>...> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\exposid{parent_} with \tcode{addressof(parent)} and
\exposid{current_} with \tcode{std::move(current)}.
\end{itemdescr}

\indexlibraryctor{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i) requires Const &&
  (@\libconcept{convertible_to}@<iterator_t<First>, iterator_t<const First>> &&
    ... && @\libconcept{convertible_to}@<iterator_t<Vs>, iterator_t<const Vs>>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\exposid{parent_} with \tcode{i.\exposid{parent_}} and
\exposid{current_} with \tcode{std::move(i.\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{operator*}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr auto operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{next}@();
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@<Const, First>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
++*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator--()
  requires @\exposconcept{cartesian-product-is-bidirectional}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{prev}@();
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator--}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@ operator--(int)
  requires @\exposconcept{cartesian-product-is-bidirectional}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = *this;
--*this;
return tmp;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator+=(difference_type x)
  requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{orig} be the value of \tcode{*this} before the call.

Let \tcode{ret} be:
\begin{itemize}
\item
If \tcode{x > 0},
the value of \tcode{*this} had \exposid{next} been called \tcode{x} times.
\item
Otherwise, if \tcode{x < 0},
the value of \tcode{*this} had \exposid{prev} been called \tcode{-x} times.
\item
Otherwise, \tcode{orig}.
\end{itemize}

\pnum
\expects
\tcode{x} is in the range
$[\tcode{ranges::distance(*this, ranges::begin(*\exposid{parent_}))},$\newline
$\tcode{ranges::distance(*this, ranges::end(*\exposid{parent_}))}]$.

\pnum
\effects
Sets the value of \tcode{*this} to \tcode{ret}.

\pnum
\returns
\tcode{*this}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibrarymember{operator-=}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator-=(difference_type x)
  requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
*this += -x;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr reference operator[](difference_type n) const
  requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *((*this) + n);}
\end{itemdescr}

\indexlibrarymember{operator==}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{equality_comparable}@<iterator_t<@\exposid{maybe-const}@<Const, First>>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator==}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \tcode{std::get<$i$>(x.\exposid{current_}) == ranges::end(std::get<$i$>(x.\exposid{parent_}->\exposid{bases_}))}
is \tcode{true}
for any integer $0 \le i \le \tcode{sizeof...(Vs)}$;
otherwise, \tcode{false}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{all-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};}
\end{itemdescr}

\indexlibrarymember{operator+}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y)
  requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(x) += y;}
\end{itemdescr}

\indexlibrarymember{operator+}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y)
  requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return y + x;}
\end{itemdescr}

\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y)
  requires @\exposconcept{cartesian-product-is-random-access}@<Const, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(x) -= y;}
\end{itemdescr}

\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  requires @\exposconcept{cartesian-is-sized-sentinel}@<Const, iterator_t, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.\exposid{distance-from}(y.\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& i, default_sentinel_t)
  requires @\exposconcept{cartesian-is-sized-sentinel}@<Const, sentinel_t, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \exposid{end-tuple} be an object of a type
that is a specialization of \tcode{tuple}, such that:
\begin{itemize}
\item
\tcode{std::get<0>(\exposid{end-tuple})} has the same value as
\tcode{ranges::end(std::get<0>(i.\exposid{parent_}->\exposid{ba\-ses_}))};
\item
\tcode{std::get<$N$>(\exposid{end-tuple})} has the same value as
\tcode{ranges::begin(std::get<$N$>(i.\exposid{parent_}->\exposid{bases_}))}
for every integer $1 \le N \le \tcode{sizeof...(Vs)}$.
\end{itemize}

\pnum
\effects
Equivalent to: \tcode{return i.\exposid{distance-from}(\exposid{end-tuple});}
\end{itemdescr}

\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t s, const @\exposid{iterator}@& i)
  requires @\exposconcept{cartesian-is-sized-sentinel}@<Const, sentinel_t, First, Vs...>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return -(i - s);}
\end{itemdescr}

\indexlibrarymember{iter_move}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});}

\pnum
\remarks
The exception specification is equivalent to
the logical \logop{and} of the following expressions:
\begin{itemize}
\item
\tcode{noexcept(ranges::iter_move(std::get<$N$>(i.\exposid{current_})))}
for every integer\newline $0 \le N \le \tcode{sizeof...(Vs)}$,
\item
\tcode{is_nothrow_move_constructible_v<range_rvalue_reference_t<\exposid{maybe-const}<Const, T>>>}\newline
for every type \tcode{T} in \tcode{First, Vs...}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{iter_swap}{cartesian_product_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@)
  requires (@\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, First>>> && ... &&
        @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{maybe-const}@<Const, Vs>>>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
For every integer $0 \le i \le \tcode{sizeof...(Vs)}$, performs:
\begin{codeblock}
ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))
\end{codeblock}

\pnum
\remarks
The exception specification is equivalent to the logical \logop{and} of the following expressions:
\begin{itemize}
\item
\tcode{noexcept(ranges::iter_swap(std::get<$i$>(l.\exposid{current_}), std::get<$i$>(r.\exposid{current_})))}
for\newline every integer $0 \le i \le \tcode{sizeof...(Vs)}$.
\end{itemize}
\end{itemdescr}

\rSec2[range.cache.latest]{Cache latest view}

\rSec3[range.cache.latest.overview]{Overview}

\pnum
\tcode{cache_latest_view} caches the last-accessed element of
its underlying sequence
so that the element does not have to be recomputed on repeated access.
\begin{note}
This is useful if computation of the element to produce is expensive.
\end{note}

\pnum
The name \tcode{views::cache_latest} denotes
a range adaptor object\iref{range.adaptor.object}.
Let \tcode{E} be an expression.
The expression \tcode{views::cache_latest(E)} is expression-equivalent to
\tcode{cache_latest_view(E)}.

\rSec3[range.cache.latest.view]{Class template \tcode{cache_latest_view}}

\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class @\libglobal{cache_latest_view}@ : public view_interface<cache_latest_view<V>> {
    V @\exposid{base_}@ = V();                                                      // \expos
    using @\exposid{cache-t}@ = conditional_t<is_reference_v<range_reference_t<V>>, // \expos
                                  add_pointer_t<range_reference_t<V>>,
                                  range_reference_t<V>>;

    @\exposid{non-propagating-cache}@<@\exposid{cache-t}@> @\exposid{cache_}@;                              // \expos

    // \ref{range.cache.latest.iterator}, class \tcode{cache_latest_view::\exposid{iterator}}
    class @\exposid{iterator}@;                                                     // \expos
    // \ref{range.cache.latest.sentinel}, class \tcode{cache_latest_view::\exposid{sentinel}}
    class @\exposid{sentinel}@;                                                     // \expos

  public:
    cache_latest_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit cache_latest_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin();
    constexpr auto end();

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };

  template<class R>
    cache_latest_view(R&&) -> cache_latest_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{cache_latest_view}%
\begin{itemdecl}
constexpr explicit cache_latest_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\indexlibrarymember{begin}{cache_latest_view}%
\begin{itemdecl}
constexpr auto begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}(*this);}
\end{itemdescr}

\indexlibrarymember{end}{cache_latest_view}%
\begin{itemdecl}
constexpr auto end();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{sentinel}(*this);}
\end{itemdescr}

\indexlibrarymember{size}{cache_latest_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::size(\exposid{base_});}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{cache_latest_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::reserve_hint(\exposid{base_});}
\end{itemdescr}

\rSec3[range.cache.latest.iterator]{Class \tcode{cache_latest_view::\exposid{iterator}}}

\indexlibraryglobal{cache_latest_view::\exposid{iiterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class cache_latest_view<V>::@\exposid{iterator}@ {
    cache_latest_view* @\exposid{parent_}@;                                 // \expos
    iterator_t<V> @\exposid{current_}@;                                     // \expos

    constexpr explicit @\exposid{iterator}@(cache_latest_view& parent);     // \expos

  public:
    using difference_type = range_difference_t<V>;
    using value_type = range_value_t<V>;
    using iterator_concept = input_iterator_tag;

    @\exposid{iterator}@(@\exposid{iterator}@&&) = default;
    @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default;

    constexpr iterator_t<V> base() &&;
    constexpr const iterator_t<V>& base() const & noexcept;

    constexpr range_reference_t<V>& operator*() const;

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);

    friend constexpr range_rvalue_reference_t<V> iter_move(const @\exposid{iterator}@& i)
      noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));

    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
      requires @\libconcept{indirectly_swappable}@<iterator_t<V>>;
  };
}
\end{codeblock}

\indexlibraryctor{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(cache_latest_view& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with
\tcode{ranges::begin(parent.\exposid{base_})}
and \exposid{parent_} with \tcode{addressof(par\-ent)}.
\end{itemdescr}

\indexlibrarymember{base}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<V> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{std::move(\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{base}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<V>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{current_}.
\end{itemdescr}

\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{parent_}@->@\exposid{cache_}@.reset();
++@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator*}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr range_reference_t<V>& operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (is_reference_v<range_reference_t<V>>) {
  if (!@\exposid{parent_}@->@\exposid{cache_}@) {
    @\exposid{parent_}@->@\exposid{cache_}@ = addressof(@\exposid{as-lvalue}@(*@\exposid{current_}@));
  }
  return **@\exposid{parent_}@->@\exposid{cache_}@;
} else {
  if (!@\exposid{parent_}@->c@\exposid{ache_}@) {
    @\exposid{parent_}@->@\exposid{cache_}@.@\exposid{emplace-deref}@(@\exposid{current_}@);
  }
  return *@\exposid{parent_}@->@\exposid{cache_}@;
}
\end{codeblock}
\begin{note}
Evaluations of \tcode{operator*} on the same iterator object
can conflict\iref{intro.races}.
\end{note}
\end{itemdescr}

\indexlibrarymember{iter_move}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr range_rvalue_reference_t<V> iter_move(const @\exposid{iterator}@& i)
  noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{iter_swap}{cache_latest_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
  requires @\libconcept{indirectly_swappable}@<iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to
\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}.
\end{itemdescr}

\rSec3[range.cache.latest.sentinel]{Class \tcode{cache_latest_view::\exposid{sentinel}}}

\indexlibraryglobal{cache_latest_view::\exposid{sentinel}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class cache_latest_view<V>::@\exposid{sentinel}@ {
    sentinel_t<V> @\exposid{end_}@ = sentinel_t<V>();                       // \expos

    constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent);     // \expos

  public:
    @\exposid{sentinel}@() = default;

    constexpr sentinel_t<V> base() const;

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y);

    friend constexpr range_difference_t<V> operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
    friend constexpr range_difference_t<V> operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
  };
}
\end{codeblock}

\indexlibraryctor{cache_latest_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}.
\end{itemdescr}

\indexlibrarymember{base}{cache_latest_view::\exposid{sentinel}}%
\begin{itemdecl}
constexpr sentinel_t<V> base() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{end_}.
\end{itemdescr}

\indexlibrarymember{operator==}{cache_latest_view::\exposid{iterator}}%
\indexlibrarymember{operator==}{cache_latest_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == y.\exposid{end_}}.
\end{itemdescr}

\indexlibrarymember{operator-}{cache_latest_view::\exposid{iterator}}%
\indexlibrarymember{operator-}{cache_latest_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr range_difference_t<V> operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} - y.\exposid{end_}}.
\end{itemdescr}

\indexlibrarymember{operator-}{cache_latest_view::\exposid{iterator}}%
\indexlibrarymember{operator-}{cache_latest_view::\exposid{sentinel}}%
\begin{itemdecl}
friend constexpr range_difference_t<V> operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<V>, iterator_t<V>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{end_} - y.\exposid{current_}}.
\end{itemdescr}

\rSec2[range.as.input]{As input view}

\rSec3[range.as.input.overview]{Overview}

\pnum
\tcode{as_input_view} presents a view of an underlying sequence
as an input-only non-common range.
\begin{note}
This is useful to avoid overhead
that can be necessary to provide support for the operations
needed for greater iterator strength.
\end{note}

\pnum
The name \tcode{views::as_input} denotes
a range adaptor object\iref{range.adaptor.object}.
Let \tcode{E} be an expression and let \tcode{T} be \tcode{decltype((E))}.
The expression \tcode{views::as_input(E)} is expression-equivalent to:
\begin{itemize}
\item
\tcode{views::all(E)}
if \tcode{T} models \libconcept{input_range},
does not satisfy \libconcept{common_range}, and
does not satisfy \libconcept{forward_range}.
\item
Otherwise, \tcode{as_input_view(E)}.
\end{itemize}

\rSec3[range.as.input.view]{Class template \tcode{as_input_view}}

\indexlibraryglobal{as_input_view}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  class as_input_view : public view_interface<as_input_view<V>> {
    V @\exposid{base_}@ = V();                        // \expos

    // \ref{range.as.input.iterator}, class template \tcode{as_input_view::\exposid{iterator}}
    template<bool Const> class @\exposid{iterator}@;  // \expos

  public:
    as_input_view() requires @\libconcept{default_initializable}@<V> = default;
    constexpr explicit as_input_view(V base);

    constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
    constexpr V base() && { return std::move(@\exposid{base_}@); }

    constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>);
    constexpr auto begin() const requires @\libconcept{range}@<const V>;

    constexpr auto end() requires (!@\exposconcept{simple-view}@<V>);
    constexpr auto end() const requires @\libconcept{range}@<const V>;

    constexpr auto size() requires @\libconcept{sized_range}@<V>;
    constexpr auto size() const requires @\libconcept{sized_range}@<const V>;

    constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
    constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
  };

  template<class R>
    as_input_view(R&&) -> as_input_view<views::all_t<R>>;
}
\end{codeblock}

\indexlibraryctor{as_input_view}%
\begin{itemdecl}
constexpr explicit as_input_view(V base);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{base_} with \tcode{std::move(base)}.
\end{itemdescr}

\indexlibrarymember{begin}{as_input_view}%
\begin{itemdecl}
constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}<false>(ranges::begin(\exposid{base_}));}
\end{itemdescr}

\indexlibrarymember{begin}{as_input_view}%
\begin{itemdecl}
constexpr auto begin() const requires @\libconcept{range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{iterator}<true>(ranges::begin(\exposid{base_}));}
\end{itemdescr}

\indexlibrarymember{end}{as_input_view}%
\begin{itemdecl}
constexpr auto end() requires (!@\exposconcept{simple-view}@<V>);
constexpr auto end() const requires @\libconcept{range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::end(\exposid{base_});}
\end{itemdescr}

\indexlibrarymember{size}{as_input_view}%
\begin{itemdecl}
constexpr auto size() requires @\libconcept{sized_range}@<V>;
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::size(\exposid{base_});}
\end{itemdescr}

\indexlibrarymember{reserve_hint}{as_input_view}%
\begin{itemdecl}
constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<V>;
constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@<const V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::reserve_hint(\exposid{base_});}
\end{itemdescr}

\rSec3[range.as.input.iterator]{Class template \tcode{as_input_view::\exposid{iterator}}}

\indexlibraryglobal{as_input_view::\exposid{iterator}}%
\begin{codeblock}
namespace std::ranges {
  template<@\libconcept{input_range}@ V>
    requires @\libconcept{view}@<V>
  template<bool Const>
  class as_input_view<V>::@\exposid{iterator}@ {
    using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>;                         // \expos

    iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>();             // \expos

    constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current);      // \expos

  public:
    using difference_type = range_difference_t<@\exposid{Base}@>;
    using value_type = range_value_t<@\exposid{Base}@>;
    using iterator_concept = input_iterator_tag;

    @\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposid{Base}@>> = default;

    @\exposid{iterator}@(@\exposid{iterator}@&&) = default;
    @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default;

    constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
      requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;

    constexpr iterator_t<@\exposid{Base}@> base() &&;
    constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;

    constexpr decltype(auto) operator*() const { return *@\exposid{current_}@; }

    constexpr @\exposid{iterator}@& operator++();
    constexpr void operator++(int);

    friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y);

    friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
    friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y)
      requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;

    friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
      noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));

    friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
      noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
      requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
  };
}
\end{codeblock}

\indexlibraryctor{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(current)}.
\end{itemdescr}

\indexlibraryctor{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
  requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{base}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr iterator_t<@\exposid{Base}@> base() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{std::move(\exposid{current_})}.
\end{itemdescr}

\indexlibrarymember{base}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{current_}.
\end{itemdescr}

\indexlibrarymember{operator++}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr @\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
++@\exposid{current_}@;
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator++}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
constexpr void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{++*this;}
\end{itemdescr}

\indexlibrarymember{operator==}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} == y}.
\end{itemdescr}

\indexlibrarymember{operator-}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{y - x.\exposid{current_}}.
\end{itemdescr}

\indexlibrarymember{operator-}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y)
  requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.\exposid{current_} - y}.
\end{itemdescr}

\indexlibrarymember{iter_move}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
  noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});}
\end{itemdescr}

\indexlibrarymember{iter_swap}{as_input_view::\exposid{iterator}}%
\begin{itemdecl}
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
  noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
  requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});}
\end{itemdescr}

\rSec1[coro.generator]{Range generators}

\rSec2[coroutine.generator.overview]{Overview}

\pnum
Class template \tcode{generator} presents
a view of the elements yielded by the evaluation of a coroutine.

\pnum
A \tcode{generator} generates a sequence of elements by
repeatedly resuming the coroutine from which it was returned.
Elements of the sequence are produced by the coroutine
each time a \tcode{co_yield} statement is evaluated.
When the \tcode{co_yield} statement is of the form
\tcode{co_yield elements_of(r)},
each element of the range \tcode{r}
is successively produced as an element of the sequence.
\begin{example}
\begin{codeblock}
generator<int> ints(int start = 0) {
  while (true)
    co_yield start++;
}

void f() {
  for (auto i : ints() | views::take(3))
    cout << i << ' ';       // prints \tcode{0 1 2}
}
\end{codeblock}
\end{example}

\rSec2[generator.syn]{Header \tcode{<generator>} synopsis}

\indexheader{generator}%
\begin{codeblock}
namespace std {
  // \ref{coro.generator.class}, class template \tcode{generator}
  template<class Ref, class Val = void, class Allocator = void>
    class generator;

  namespace pmr {
    template<class Ref, class Val = void>
      using generator = std::generator<Ref, Val, polymorphic_allocator<>>;
  }
}
\end{codeblock}

\rSec2[coro.generator.class]{Class template \tcode{generator}}

\begin{codeblock}
namespace std {
  template<class Ref, class Val = void, class Allocator = void>
  class @\libglobal{generator}@ : public ranges::view_interface<generator<Ref, Val, Allocator>> {
  private:
    using @\exposid{value}@ = conditional_t<is_void_v<Val>, remove_cvref_t<Ref>, Val>;  // \expos
    using @\exposid{reference}@ = conditional_t<is_void_v<Val>, Ref&&, Ref>;          // \expos

    // \ref{coro.generator.iterator}, class \tcode{generator::\exposid{iterator}}
    class @\exposidnc{iterator}@;                                                     // \expos

  public:
    using yielded =
      conditional_t<is_reference_v<@\exposid{reference}@>, @\exposid{reference}@, const @\exposid{reference}@&>;

    // \ref{coro.generator.promise}, class \tcode{generator::promise_type}
    class promise_type;

    generator(const generator&) = delete;
    generator(generator&& other) noexcept;

    ~generator();

    generator& operator=(generator other) noexcept;

    @\exposid{iterator}@ begin();
    default_sentinel_t end() const noexcept;

  private:
    coroutine_handle<promise_type> @\exposid{coroutine_}@ = nullptr;  // \expos
    unique_ptr<stack<coroutine_handle<>>> @\exposid{active_}@;        // \expos
  };
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{Allocator} is not \tcode{void},
\tcode{allocator_traits<Allocator>::pointer} is a pointer type.
\item
\exposid{value} is a cv-unqualified object type.
\item
\exposid{reference} is either a reference type, or
a cv-unqualified object type that models \libconcept{copy_constructible}.
\item
Let \tcode{RRef} denote \tcode{remove_reference_t<\exposid{reference}>\&\&}
if \exposid{reference} is a reference type,
and \exposid{reference} otherwise.
Each of:
\begin{itemize}
\item \tcode{\libconcept{common_reference_with}<\exposid{reference}\&\&, \exposid{value}\&>},
\item \tcode{\libconcept{common_reference_with}<\exposid{reference}\&\&, RRef\&\&>}, and
\item \tcode{\libconcept{common_reference_with}<RRef\&\&, const \exposid{value}\&>}
\end{itemize}
is modeled.
\begin{note}
These requirements ensure the exposition-only \exposid{iterator} type
can model \libconcept{indirectly_readable} and thus \libconcept{input_iterator}.
\end{note}
\end{itemize}

\pnum
If \tcode{Allocator} is not \tcode{void},
it shall meet the \oldconcept{Allocator} requirements.

\pnum
Specializations of \tcode{generator} model
\libconcept{view} and \libconcept{input_range}.

\pnum
The behavior of a program that adds a specialization
for \tcode{generator} is undefined.

\rSec2[coro.generator.members]{Members}

\indexlibraryctor{generator}%
\begin{itemdecl}
generator(generator&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{coroutine_} with
\tcode{exchange(other.\exposid{coroutine_}, \{\})} and
\exposid{active_} with
\tcode{exchange(\brk{}other.\exposid{active_}, nullptr)}.

\pnum
\begin{note}
Iterators previously obtained from \tcode{other} are not invalidated;
they become iterators into \tcode{*this}.
\end{note}
\end{itemdescr}

\indexlibrarydtor{generator}%
\begin{itemdecl}
~generator();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if (@\exposid{coroutine_}@) {
  @\exposid{coroutine_}@.destroy();
}
\end{codeblock}

\pnum
\begin{note}
Ownership of recursively yielded generators
is held in awaitable objects
in the coroutine frame of the yielding generator,
so destroying the root generator
effectively destroys the entire stack of yielded generators.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator=}{generator}%
\begin{itemdecl}
generator& operator=(generator other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
swap(@\exposid{coroutine_}@, other.@\exposid{coroutine_}@);
swap(@\exposid{active_}@, other.@\exposid{active_}@);
\end{codeblock}

\pnum
\returns
\tcode{*this}.

\pnum
\begin{note}
Iterators previously obtained from \tcode{other} are not invalidated;
they become iterators into \tcode{*this}.
\end{note}
\end{itemdescr}

\indexlibrarymember{begin}{generator}%
\begin{itemdecl}
@\exposid{iterator}@ begin();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\exposid{coroutine_} refers to a coroutine
suspended at its initial suspend point\iref{dcl.fct.def.coroutine}.

\pnum
\effects
Pushes \exposid{coroutine_} into \tcode{*\exposid{active_}},
then evaluates \tcode{\exposid{coroutine_}.resume()}.

\pnum
\returns
An \exposid{iterator} object
whose member \exposid{coroutine_}
refers to the same coroutine as does
\exposid{coroutine_}.

\pnum
\begin{note}
A program that calls \tcode{begin} more than once on the same generator
has undefined behavior.
\end{note}
\end{itemdescr}

\indexlibrarymember{end}{generator}%
\begin{itemdecl}
default_sentinel_t end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{default_sentinel}.
\end{itemdescr}

\rSec2[coro.generator.promise]{Class \tcode{generator::promise_type}}

\begin{codeblock}
namespace std {
  template<class Ref, class Val, class Allocator>
  class generator<Ref, Val, Allocator>::promise_type {
  public:
    generator get_return_object() noexcept;

    suspend_always initial_suspend() const noexcept { return {}; }
    auto final_suspend() noexcept;

    suspend_always yield_value(yielded val) noexcept;

    auto yield_value(const remove_reference_t<yielded>& lval)
      requires is_rvalue_reference_v<yielded> &&
        @\libconcept{constructible_from}@<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>;

    template<class R2, class V2, class Alloc2, class Unused>
      requires @\libconcept{same_as}@<typename generator<R2, V2, Alloc2>::yielded, yielded>
        auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept;
    template<class R2, class V2, class Alloc2, class Unused>
      requires @\libconcept{same_as}@<typename generator<R2, V2, Alloc2>::yielded, yielded>
        auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&, Unused> g) noexcept;

    template<ranges::@\libconcept{input_range}@ R, class Alloc>
      requires @\libconcept{convertible_to}@<ranges::range_reference_t<R>, yielded>
        auto yield_value(ranges::elements_of<R, Alloc> r);

    void await_transform() = delete;

    void return_void() const noexcept {}
    void unhandled_exception();

    void* operator new(size_t size)
      requires @\libconcept{same_as}@<Allocator, void> || @\libconcept{default_initializable}@<Allocator>;

    template<class Alloc, class... Args>
      void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...);

    template<class This, class Alloc, class... Args>
      void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc,
                         const Args&...);

    void operator delete(void* pointer, size_t size) noexcept;

  private:
    add_pointer_t<yielded> @\exposid{value_}@ = nullptr;    // \expos
    exception_ptr @\exposid{except_}@;                      // \expos
  };
}
\end{codeblock}

\indexlibrarymember{get_return_object}{generator::promise_type}%
\begin{itemdecl}
generator get_return_object() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{generator} object whose member \exposid{coroutine_}
is \tcode{coroutine_handle<promise_type>::\brk{}from_promise(*this)},
and whose member \exposid{active_} points to an empty stack.
\end{itemdescr}

\indexlibrarymember{final_suspend}{generator::promise_type}%
\begin{itemdecl}
auto final_suspend() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
A handle referring to the coroutine
whose promise object is \tcode{*this}
is at the top of \tcode{*\exposid{active_}}
of some \tcode{generator} object \tcode{x}.
This function is called by that coroutine
upon reaching its final suspend point\iref{dcl.fct.def.coroutine}.

\pnum
\returns
An awaitable object of unspecified type\iref{expr.await}
whose member functions arrange for the
calling coroutine to be suspended,
pop the coroutine handle
from the top of \tcode{*x.\exposid{active_}},
and resume execution of the coroutine referred to by
\tcode{x.\exposid{active_}->top()}
if \tcode{*x.\exposid{active_}} is not empty.
If it is empty, control flow returns to the
current coroutine caller or resumer\iref{dcl.fct.def.coroutine}.
\end{itemdescr}

\indexlibrarymember{yield_value}{generator::promise_type}%
\begin{itemdecl}
suspend_always yield_value(yielded val) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{\exposid{value_} = addressof(val)}.

\pnum
\returns
\tcode{\{\}}.
\end{itemdescr}

\indexlibrarymember{yield_value}{generator::promise_type}%
\begin{itemdecl}
auto yield_value(const remove_reference_t<yielded>& lval)
  requires is_rvalue_reference_v<yielded> &&
    @\libconcept{constructible_from}@<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
A handle referring to the coroutine
whose promise object is \tcode{*this}
is at the top of \tcode{*\exposid{active_}}
of some \tcode{generator} object.

\pnum
\returns
An awaitable object of an unspecified type\iref{expr.await}
that stores an object of type \tcode{remove_cvref_t<yielded>}
direct-non-list-initialized with \tcode{lval},
whose member functions arrange for
\exposid{value_} to point to that stored object
and then suspend the coroutine.

\pnum
\throws
Any exception thrown by the initialization of the stored object.

\pnum
\remarks
A \grammarterm{yield-expression} that calls this function
has type \tcode{void}\iref{expr.yield}.
\end{itemdescr}

\indexlibrarymember{yield_value}{generator::promise_type}%
\begin{itemdecl}
template<class R2, class V2, class Alloc2, class Unused>
  requires @\libconcept{same_as}@<typename generator<R2, V2, Alloc2>::yielded, yielded>
  auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept;
template<class R2, class V2, class Alloc2, class Unused>
  requires @\libconcept{same_as}@<typename generator<R2, V2, Alloc2>::yielded, yielded>
  auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&, Unused> g) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
A handle referring to the coroutine
whose promise object is \tcode{*this}
is at the top of \tcode{*\exposid{active_}}
of some \tcode{generator} object \tcode{x}.
The coroutine referred to by
\tcode{g.range.\exposid{coroutine_}}
is suspended at its initial suspend point.

\pnum
\returns
An awaitable object of an unspecified type\iref{expr.await}
into which \tcode{g.range} is moved,
whose member \tcode{await_ready} returns \tcode{false},
whose member \tcode{await_suspend}
% FIXME: The mbox prevents TeX from adding a bizarre hyphen after coroutine_.
pushes \tcode{g.range.}\mbox{\exposid{coroutine_}}
into \tcode{*x.\exposid{active_}}
and resumes execution of the coroutine referred to
by \tcode{g.range.\brk{}\exposid{coroutine_}}, and
whose member \tcode{await_resume} evaluates
\tcode{rethrow_exception(\exposid{except_})}
if \tcode{bool(\exposid{ex\-cept_})} is \tcode{true}.
If \tcode{bool(\exposid{except_})} is \tcode{false},
the \tcode{await_resume} member has no effects.

\pnum
\remarks
A \grammarterm{yield-expression} that calls one of these functions
has type \tcode{void}\iref{expr.yield}.
\end{itemdescr}

\indexlibrarymember{yield_value}{generator::promise_type}%
\begin{itemdecl}
template<ranges::@\libconcept{input_range}@ R, class Alloc>
  requires @\libconcept{convertible_to}@<ranges::range_reference_t<R>, yielded>
  auto yield_value(ranges::elements_of<R, Alloc> r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto nested = [](allocator_arg_t, Alloc, ranges::iterator_t<R> i, ranges::sentinel_t<R> s)
  -> generator<yielded, void, Alloc> {
    for (; i != s; ++i) {
      co_yield static_cast<yielded>(*i);
    }
  };
return yield_value(ranges::elements_of(nested(
  allocator_arg, r.allocator, ranges::begin(r.range), ranges::end(r.range))));
\end{codeblock}

\pnum
\begin{note}
A \grammarterm{yield-expression} that calls this function
has type \tcode{void}\iref{expr.yield}.
\end{note}
\end{itemdescr}

\indexlibrarymember{unhandled_exception}{generator::promise_type}%
\begin{itemdecl}
void unhandled_exception();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
A handle referring to the coroutine whose promise object is \tcode{*this}
is at the top of \tcode{*\exposid{active_}}
of some \tcode{generator} object \tcode{x}.

\pnum
\effects
If the handle referring to the coroutine
whose promise object is \tcode{*this}
is the sole element of \tcode{*x.\exposid{active_}},
equivalent to \tcode{throw},
otherwise, assigns \tcode{current_exception()} to \exposid{except_}.
\end{itemdescr}

\indexlibrarymember{operator new}{generator::promise_type}%
\begin{itemdecl}
void* operator new(size_t size)
  requires @\libconcept{same_as}@<Allocator, void> || @\libconcept{default_initializable}@<Allocator>;

template<class Alloc, class... Args>
  void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...);

template<class This, class Alloc, class... Args>
  void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc,
                     const Args&...);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{A} be
\begin{itemize}
\item
\tcode{Allocator}, if it is not \tcode{void},
\item
\tcode{Alloc} for the overloads with a template parameter \tcode{Alloc}, or
\item
\tcode{allocator<void>} otherwise.
\end{itemize}
Let \tcode{B} be \tcode{allocator_traits<A>::template rebind_alloc<U>}
where \tcode{U} is an unspecified type whose size and alignment
are both \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}.

\pnum
\mandates
\tcode{allocator_traits<B>::pointer} is a pointer type.
For the overloads with a template parameter \tcode{Alloc},
\tcode{\libconcept{same_as}<Allocator, void> || \libconcept{convertible_to}<const Alloc\&, Allocator>}
is modeled.

\pnum
\effects
Initializes an allocator \tcode{b} of type \tcode{B} with \tcode{A(alloc)},
for the overloads with a function parameter \tcode{alloc},
and with \tcode{A()} otherwise.
Uses \tcode{b} to allocate storage for the smallest array
of \tcode{U} sufficient to provide storage for
a coroutine state of size \tcode{size}, and
unspecified additional state necessary to ensure that
\tcode{operator delete} can later deallocate this memory block
with an allocator equal to \tcode{b}.

\pnum
\returns
A pointer to the allocated storage.
\end{itemdescr}

\indexlibrarymember{operator delete}{generator::promise_type}%
\begin{itemdecl}
void operator delete(void* pointer, size_t size) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{pointer} was returned from an invocation of
one of the above overloads of \tcode{operator new}
with a \tcode{size} argument equal to \tcode{size}.

\pnum
\effects
Deallocates the storage pointed to by \tcode{pointer}
using an allocator equivalent to that used to allocate it.
\end{itemdescr}

\rSec2[coro.generator.iterator]{Class \tcode{generator::\exposid{iterator}}}

\begin{codeblock}
namespace std {
  template<class Ref, class Val, class Allocator>
  class generator<Ref, Val, Allocator>::@\exposid{iterator}@ {
  public:
    using value_type = @\exposid{value}@;
    using difference_type = ptrdiff_t;

    @\exposid{iterator}@(@\exposid{iterator}@&& other) noexcept;
    @\exposid{iterator}@& operator=(@\exposid{iterator}@&& other) noexcept;

    @\exposid{reference}@ operator*() const noexcept(is_nothrow_copy_constructible_v<@\exposid{reference}@>);
    @\exposid{iterator}@& operator++();
    void operator++(int);

    friend bool operator==(const @\exposid{iterator}@& i, default_sentinel_t);

  private:
    coroutine_handle<promise_type> @\exposid{coroutine_}@; // \expos
  };
}
\end{codeblock}

\indexlibraryctor{generator::\exposid{iterator}}%
\begin{itemdecl}
@\exposid{iterator}@(@\exposid{iterator}@&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{coroutine_}
with \tcode{exchange(other.\exposid{coroutine_}, \{\})}.
\end{itemdescr}

\indexlibrarymember{operator=}{generator::\exposid{iterator}}%
\begin{itemdecl}
@\exposid{iterator}@& operator=(@\exposid{iterator}@&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to
\tcode{\exposid{coroutine_} = exchange(other.\exposid{coroutine_}, \{\})}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator*}{generator::\exposid{iterator}}%
\begin{itemdecl}
@\exposid{reference}@ operator*() const noexcept(is_nothrow_copy_constructible_v<@\exposid{reference}@>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
For some \tcode{generator} object \tcode{x},
\exposid{coroutine_} is in \tcode{*x.\exposid{active_}} and
\tcode{x.\exposid{active_}->top()} refers to
a suspended coroutine with promise object \tcode{p}.

\pnum
\effects
Equivalent to:
\tcode{return static_cast<\exposid{reference}>(*p.\exposid{value_});}
\end{itemdescr}

\indexlibrarymember{operator++}{generator::\exposid{iterator}}%
\begin{itemdecl}
@\exposid{iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
For some \tcode{generator} object \tcode{x},
\exposid{coroutine_} is in \tcode{*x.\exposid{active_}}.

\pnum
\effects
Equivalent to \tcode{x.\exposid{active_}->top().resume()}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{generator::\exposid{iterator}}%
\begin{itemdecl}
void operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{++*this}.
\end{itemdescr}

\indexlibrarymember{operator==}{generator::\exposid{iterator}}%
\begin{itemdecl}
friend bool operator==(const @\exposid{iterator}@& i, default_sentinel_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return i.\exposid{coroutine_}.done();}
\end{itemdescr}
