Standard library header <ranges>

This header is part of the ranges library.

Namespace aliases

namespace std {
    namespace view = ranges::view;
}

The namespace alias std::view is provided as a shorthand for std::ranges::view.

Concepts

Range concepts
Defined in namespace std::ranges
specifies that a type is a range, that is, it provides a begin iterator and an end sentinel
(concept)
specifies that a range knows its size in constant time
(concept)
specifies that a range is a view, that is, it has constant time copy/move/assignment
(concept)
specifies a range whose iterator type satisfies InputIterator
(concept)
specifies a range whose iterator type satisfies OutputIterator
(concept)
specifies a range whose iterator type satisfies ForwardIterator
(concept)
specifies a range whose iterator type satisfies BidirectionalIterator
(concept)
specifies a range whose iterator type satisfies RandomAccessIterator
(concept)
specifies a range whose iterator type satisfies ContiguousIterator
(concept)
specifies that a range has identical iterator and sentinel types
(concept)
specifies the requirements for a Range to be safely convertible to a View
(concept)

Classes

Range primitives
Defined in namespace std::ranges
obtains the iterator and sentinel types of a range
(alias template)
Views
Defined in namespace std::ranges
helper class template for defining Views, using the curiously recurring template pattern
(class template)
combines an iterator-sentinel pair into a View
(class template)
Dangling iterator handling
Defined in namespace std::ranges
a placeholder type indicating that an iterator or a subrange should not be returned since it would be dangling
(class)
obtains iterator type or subrange type of a Range which also models __ForwardingRange
(alias template)
Factories
Defined in namespace std::ranges
an empty View with no elements
(class template) (variable template)
a View that contains a single element of a specified value
(class template) (customization point object)
a View consisting of a sequence generated by repeatedly incrementing an initial value
(class template) (customization point object)
creates a subrange from an iterator and a count
(customization point object)
Adaptors
Defined in namespace std::ranges
a View that includes all elements of a Range
(alias template) (range adaptor object)
a View of the elements of some other Range
(class template)
a View that consists of the elements of a Range that satisfies a predicate
(class template) (range adaptor object)
a View of a sequence that applies a transformation function to each element
(class template) (range adaptor object)
a View consisting of the first N elements of another View
(class template) (range adaptor object)
a View consisting of the sequence obtained from flattening a View of Ranges
(class template) (range adaptor object)
a View over the subranges obtained from splitting another View using a delimiter
(class template) (range adaptor object)
converts a View into a CommonRange
(class template) (range adaptor object)
a View that iterates over the elements of another bidirectional view in reverse order
(class template) (range adaptor object)

Customization point objects

Range access
Defined in namespace std::ranges
returns an iterator to the beginning of a range
(customization point object)
returns an iterator to the end of a range
(customization point object)
returns a reverse iterator to a range
(customization point object)
returns a reverse end iterator to a range
(customization point object)
obtains the size of a range whose size can be calculated in constant time
(customization point object)
checks whether a range is empty
(customization point object)
obtains a pointer to the beginning of a contiguous range
(customization point object)

Synopsis

#include <initializer_list>
#include <iterator>
 
namespace std::ranges {
  inline namespace /* unspecified */ {
    // range access
    inline constexpr /* unspecified */ begin = /* unspecified */;
    inline constexpr /* unspecified */ end = /* unspecified */;
    inline constexpr /* unspecified */ cbegin = /* unspecified */;
    inline constexpr /* unspecified */ cend = /* unspecified */;
    inline constexpr /* unspecified */ rbegin = /* unspecified */;
    inline constexpr /* unspecified */ rend = /* unspecified */;
    inline constexpr /* unspecified */ crbegin = /* unspecified */;
    inline constexpr /* unspecified */ crend = /* unspecified */;
 
    inline constexpr /* unspecified */ size = /* unspecified */;
    inline constexpr /* unspecified */ empty = /* unspecified */;
    inline constexpr /* unspecified */ data = /* unspecified */;
    inline constexpr /* unspecified */ cdata = /* unspecified */;
  }
 
  // ranges
  template<class T>
    using iterator_t = decltype(ranges::begin(declval<T&>()));
 
  template<class T>
    using sentinel_t = decltype(ranges::end(declval<T&>()));
 
  template<class T>
    concept Range = /* see definition */;
 
  // sized ranges
  template<class>
    inline constexpr bool disable_sized_range = false;
 
  template<class T>
    concept SizedRange = /* see definition */;
 
  // views
  template<class T>
    inline constexpr bool enable_view = /* see definition */;
 
  struct view_base { };
 
  template<class T>
    concept View = /* see definition */;
 
  // other range refinements
  template<class R, class T>
    concept OutputRange = /* see definition */;
 
  template<class T>
    concept InputRange = /* see definition */;
 
  template<class T>
    concept ForwardRange = /* see definition */;
 
  template<class T>
    concept BidirectionalRange = /* see definition */;
 
  template<class T>
    concept RandomAccessRange = /* see definition */;
 
  template<class T>
    concept ContiguousRange = /* see definition */;
 
  template<class T>
    concept CommonRange = /* see definition */;
 
  template<class T>
    concept ViewableRange = /* see definition */;
 
  // class template view_interface
  template<class D>
    requires is_class_v<D> && Same<D, remove_cv_t<D>>
  class view_interface;
 
  // sub-ranges
  enum class subrange_kind : bool { unsized, sized };
 
  template<Iterator I, Sentinel<I> S = I, subrange_kind K = /* see definition */>
    requires (K == subrange_kind::sized || !SizedSentinel<S, I>)
  class subrange;
 
  // dangling iterator handling
  struct dangling;
 
  template<Range R>
    using safe_iterator_t = conditional_t<__ForwardingRange<R>, iterator_t<R>, dangling>;
 
  template<Range R>
    using safe_subrange_t =
      conditional_t<__ForwardingRange<R>, subrange<iterator_t<R>>, dangling>;
 
  // empty view
  template<class T>
    requires is_object_v<T>
  class empty_view;
 
  namespace view {
    template<class T>
      inline constexpr empty_view<T> empty{};
  }
 
  // single view
  template<CopyConstructible T>
    requires is_object_v<T>
  class single_view;
 
  namespace view { inline constexpr /* unspecified */ single = /* unspecified */; }
 
  // iota view
  template<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t>
    requires __WeaklyEqualityComparableWith<W, Bound>
  class iota_view;
 
  namespace view { inline constexpr /* unspecified */ iota = /* unspecified */; }
 
  // all view
  namespace view { inline constexpr /* unspecified */ all = /* unspecified */; }
 
  template<ViewableRange R>
    using all_view = decltype(view::all(declval<R>()));
 
  template<Range R>
    requires is_object_v<R>
  class ref_view;
 
  // filter view
  template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred>
    requires View<V> && is_object_v<Pred>
  class filter_view;
 
  namespace view { inline constexpr /* unspecified */ filter = /* unspecified */; }
 
  // transform view
  template<InputRange V, CopyConstructible F>
    requires View<V> && is_object_v<F> &&
             RegularInvocable<F&, iter_reference_t<iterator_t<V>>>
  class transform_view;
 
  namespace view { inline constexpr /* unspecified */ transform = /* unspecified */; }
 
  // take view
  template<View> class take_view;
 
  namespace view { inline constexpr /* unspecified */ take = /* unspecified */; }
 
  // join view
  template<InputRange V>
    requires View<V> && InputRange<iter_reference_t<iterator_t<V>>> &&
             (is_reference_v<iter_reference_t<iterator_t<V>>> ||
              View<iter_value_t<iterator_t<V>>>)
  class join_view;
 
  namespace view { inline constexpr /* unspecified */ join = /* unspecified */; }
 
  // split view
  template<class R>
    concept __TinyRange = /* see definition */;   // exposition only
 
  template<InputRange V, ForwardRange Pattern>
    requires View<V> && View<Pattern> &&
             IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (ForwardRange<V> || __TinyRange<Pattern>)
  class split_view;
 
  namespace view { inline constexpr /* unspecified */ split = /* unspecified */; }
 
  // counted view
  namespace view { inline constexpr /* unspecified */ counted = /* unspecified */; }
 
  // common view
  template<View V>
    requires (!CommonRange<V>)
  class common_view;
 
  namespace view { inline constexpr /* unspecified */ common = /* unspecified */; }
 
  // reverse view
  template<View V>
    requires BidirectionalRange<V>
  class reverse_view;
 
  namespace view { inline constexpr /* unspecified */ reverse = /* unspecified */; }
}
 
namespace std {
  namespace view = ranges::view;
 
  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;
  };
}

Concept Range

namespace std::ranges {
  template<class T>
    concept __RangeImpl =          // exposition only
      requires(T&& t) {
        ranges::begin(std::forward<T>(t));// sometimes equality-preserving (see definition)
        ranges::end(std::forward<T>(t));
      };
 
  template<class T>
    concept Range = __RangeImpl<T&>;
 
  template<class T>
    concept __ForwardingRange =    // exposition only
      Range<T> && __RangeImpl<T>;
}

Concept SizedRange

namespace std::ranges {
  template<class T>
    concept SizedRange =
      Range<T> &&
      !disable_sized_range<remove_cvref_t<T>> &&
      requires(T& t) { ranges::size(t); };
}

Concept View

namespace std::ranges {
  template<class T>
    inline constexpr bool enable_view = /* see definition */;
 
  template<class T>
    concept View =
      Range<T> && Semiregular<T> && enable_view<T>;
}

Concept OutputRange

namespace std::ranges {
  template<class R, class T>
    concept OutputRange =
      Range<R> && OutputIterator<iterator_t<R>, T>;
}

Concept InputRange

namespace std::ranges {
  template<class T>
    concept InputRange =
      Range<T> && InputIterator<iterator_t<T>>;
}

Concept ForwardRange

namespace std::ranges {
  template<class T>
    concept ForwardRange =
      InputRange<T> && ForwardIterator<iterator_t<T>>;
}

Concept BidirectionalRange

namespace std::ranges {
  template<class T>
    concept BidirectionalRange =
      ForwardRange<T> && BidirectionalIterator<iterator_t<T>>;
}

Concept RandomAccessRange

namespace std::ranges {
  template<class T>
    concept RandomAccessRange =
      BidirectionalRange<T> && RandomAccessIterator<iterator_t<T>>;
}

Concept ContiguousRange

namespace std::ranges {
  template<class T>
    concept ContiguousRange =
     RandomAccessRange<T> && ContiguousIterator<iterator_t<T>> &&
      requires(T& t) {
        { ranges::data(t) } -> Same<add_pointer_t<iter_reference_t<iterator_t<T>>>>;
      };
}

Concept CommonRange

namespace std::ranges {
  template<class T>
    concept CommonRange =
      Range<T> && Same<iterator_t<T>, sentinel_t<T>>;
}

Concept ViewableRange

namespace std::ranges {
  template<class T>
    concept ViewableRange =
      Range<T> && (__ForwardingRange<T> || View<decay_t<T>>);
}

Helper concepts

namespace std::ranges { // unspecified, for name lookup only
  template<class R>
    concept __SimpleView =                        // exposition only
      View<R> && Range<const R> &&
      Same<iterator_t<R>, iterator_t<const R>> &&
      Same<sentinel_t<R>, sentinel_t<const R>>;
 
  template<InputIterator I>
    concept __HasArrow =                          // exposition only
      is_pointer_v<I> || requires(I i) { i.operator->(); };
 
  template<class T, class U>
    concept __NotSameAs =                         // exposition only
      !Same<remove_cvref_t<T>, remove_cvref_t<U>>;
 
  template<class I>
    concept _Decrementable =                      // exposition only
      Incrementable<I> && requires(I i) {
        { --i } -> Same<I&>;
        { i-- } -> Same<I>;
      };
 
  template<class I>
    concept _Advanceable =                        // exposition only
      _Decrementable<I> && StrictTotallyOrdered<I> &&
      requires(I i, const I j, const iter_difference_t<I> n) {
        { i += n } -> Same<I&>;
        { i -= n } -> Same<I&>;
        { j +  n } -> Same<I>;
        { n +  j } -> Same<I>;
        { j -  n } -> Same<I>;
        { j -  j } -> Same<iter_difference_t<I>>;
      };
}

Note: These names are only for exposition, they are not part of the interface.

Class template std::ranges::view_interface

namespace std::ranges {
  template<class D>
    requires is_class_v<D> && Same<D, remove_cv_t<D>>
  class view_interface : public view_base {
  private:
    constexpr D& derived() noexcept {                   // exposition only
      return static_cast<D&>(*this);
    }
    constexpr const D& derived() const noexcept {       // exposition only
      return static_cast<const D&>(*this);
    }
  public:
    constexpr bool empty() requires ForwardRange<D> {
      return ranges::begin(derived()) == ranges::end(derived());
    }
    constexpr bool empty() const requires ForwardRange<const D> {
      return ranges::begin(derived()) == ranges::end(derived());
    }
 
    constexpr explicit operator bool()
      requires requires { ranges::empty(derived()); } {
        return !ranges::empty(derived());
      }
    constexpr explicit operator bool() const
      requires requires { ranges::empty(derived()); } {
        return !ranges::empty(derived());
      }
 
    constexpr auto data() requires ContiguousIterator<iterator_t<D>> {
      return ranges::empty(derived()) ? nullptr : addressof(*ranges::begin(derived()));
    }
    constexpr auto data() const
      requires Range<const D> && ContiguousIterator<iterator_t<const D>> {
        return ranges::empty(derived()) ? nullptr : addressof(*ranges::begin(derived()));
      }
 
    constexpr auto size() requires ForwardRange<D> &&
      SizedSentinel<sentinel_t<D>, iterator_t<D>> {
        return ranges::end(derived()) - ranges::begin(derived());
      }
    constexpr auto size() const requires ForwardRange<const D> &&
      SizedSentinel<sentinel_t<const D>, iterator_t<const D>> {
        return ranges::end(derived()) - ranges::begin(derived());
      }
 
    constexpr decltype(auto) front() requires ForwardRange<D>;
    constexpr decltype(auto) front() const requires ForwardRange<const D>;
 
    constexpr decltype(auto) back() requires BidirectionalRange<D> && CommonRange<D>;
    constexpr decltype(auto) back() const
      requires BidirectionalRange<const D> && CommonRange<const D>;
 
    template<RandomAccessRange R = D>
      constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n) {
        return ranges::begin(derived())[n];
      }
    template<RandomAccessRange R = const D>
      constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n) const {
        return ranges::begin(derived())[n];
      }
  };
}

Class template std::ranges::subrange

namespace std::ranges {
  template<class T>
    concept __PairLike =                                // exposition only
      !is_reference_v<T> && requires(T t) {
        typename tuple_size<T>::type;   // ensures tuple_­size<T> is complete
        requires DerivedFrom<tuple_size<T>, integral_constant<size_t, 2>>;
        typename tuple_element_t<0, remove_const_t<T>>;
        typename tuple_element_t<1, remove_const_t<T>>;
        { get<0>(t) } -> const tuple_element_t<0, T>&;
        { get<1>(t) } -> const tuple_element_t<1, T>&;
      };
 
  template<class T, class U, class V>
    concept __PairLikeConvertibleTo =                   // exposition only
      !Range<T> && __PairLike<remove_reference_t<T>> &&
      requires(T&& t) {
        { get<0>(std::forward<T>(t)) } -> ConvertibleTo<U>;
        { get<1>(std::forward<T>(t)) } -> ConvertibleTo<V>;
      };
 
  template<class T, class U, class V>
    concept __PairLikeConvertibleFrom =                 // exposition only
      !Range<T> && __PairLike<T> && Constructible<T, U, V>;
 
  template<class T>
    concept __IteratorSentinelPair =                    // exposition only
      !Range<T> && __PairLike<T> &&
      Sentinel<tuple_element_t<1, T>, tuple_element_t<0, T>>;
 
  template<Iterator I, Sentinel<I> S = I, subrange_kind K =
      SizedSentinel<S, I> ? subrange_kind::sized : subrange_kind::unsized>
    requires (K == subrange_kind::sized || !SizedSentinel<S, I>)
  class subrange : public view_interface<subrange<I, S, K>> {
  private:
    static constexpr bool StoreSize =                   // exposition only
      K == subrange_kind::sized && !SizedSentinel<S, I>;
    I begin_ = I();                                     // exposition only
    S end_ = S();                                       // exposition only
    iter_difference_t<I> size_ = 0;                     // exposition only; present only
                                                        // when StoreSize is true
  public:
    subrange() = default;
 
    constexpr subrange(I i, S s) requires (!StoreSize);
 
    constexpr subrange(I i, S s, iter_difference_t<I> n)
      requires (K == subrange_kind::sized);
 
    template<__NotSameAs<subrange> R>
      requires __ForwardingRange<R> &&
        ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S>
    constexpr subrange(R&& r) requires (!StoreSize || SizedRange<R>);
 
    template<__ForwardingRange R>
      requires ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S>
    constexpr subrange(R&& r, iter_difference_t<I> n)
      requires (K == subrange_kind::sized)
        : subrange{ranges::begin(r), ranges::end(r), n}
    {}
 
    template<__NotSameAs<subrange> PairLike>
      requires __PairLikeConvertibleTo<PairLike, I, S>
    constexpr subrange(PairLike&& r) requires (!StoreSize)
      : subrange{std::get<0>(std::forward<PairLike>(r)),
                 std::get<1>(std::forward<PairLike>(r))}
    {}
 
    template<__PairLikeConvertibleTo<I, S> PairLike>
    constexpr subrange(PairLike&& r, iter_difference_t<I> n)
      requires (K == subrange_kind::sized)
      : subrange{std::get<0>(std::forward<PairLike>(r)),
                 std::get<1>(std::forward<PairLike>(r)), n}
    {}
 
    template<__NotSameAs<subrange> PairLike>
      requires __PairLikeConvertibleFrom<PairLike, const I&, const S&>
    constexpr operator PairLike() const;
 
    constexpr I begin() const;
    constexpr S end() const;
 
    constexpr bool empty() const;
    constexpr iter_difference_t<I> size() const
      requires (K == subrange_kind::sized);
 
    [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const;
    [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
      requires BidirectionalIterator<I>;
    constexpr subrange& advance(iter_difference_t<I> n);
 
    friend constexpr I begin(subrange&& r) { return r.begin(); }
    friend constexpr S end(subrange&& r) { return r.end(); }
  };
 
  template<Iterator I, Sentinel<I> S>
    subrange(I, S, iter_difference_t<I>) -> subrange<I, S, subrange_kind::sized>;
 
  template<__IteratorSentinelPair P>
    subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
 
  template<__IteratorSentinelPair P>
    subrange(P, iter_difference_t<tuple_element_t<0, P>>) ->
      subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
 
  template<__ForwardingRange R>
    subrange(R&&) ->
      subrange<iterator_t<R>, sentinel_t<R>,
               (SizedRange<R> || SizedSentinel<sentinel_t<R>, iterator_t<R>>)
                 ? subrange_kind::sized : subrange_kind::unsized>;
 
  template<__ForwardingRange R>
    subrange(R&&, iter_difference_t<iterator_t<R>>) ->
      subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
 
  template<size_t N, class I, class S, subrange_kind K>
    requires (N < 2)
  constexpr auto get(const subrange<I, S, K>& r);
}
 
namespace std {
  using ranges::get;
}

Class std::ranges::dangling

namespace std::ranges {
  struct dangling {
    constexpr dangling() noexcept = default;
    template<class... Args>
      constexpr dangling(Args&&...) noexcept { }
  };
}

Class template std::ranges::empty_view

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 ptrdiff_t size() noexcept { return 0; }
    static constexpr bool empty() noexcept { return true; }
 
    friend constexpr T* begin(empty_view) noexcept { return nullptr; }
    friend constexpr T* end(empty_view) noexcept { return nullptr; }
  };
}

Class template std::ranges::empty_view

namespace std::ranges {
  template<CopyConstructible T>
    requires is_object_v<T>
  class single_view : public view_interface<single_view<T>> {
  private:
    semiregular<T> value_;      // exposition only
  public:
    single_view() = default;
    constexpr explicit single_view(const T& t);
    constexpr explicit single_view(T&& t);
    template<class... Args>
      requires Constructible<T, Args...>
    constexpr 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 ptrdiff_t size() noexcept;
    constexpr T* data() noexcept;
    constexpr const T* data() const noexcept;
  };
}

Class template std::ranges::iota_view

namespace std::ranges {
  template<class I>
    concept _Decrementable =    // exposition only
      /* see definition */;
  template<class I>
    concept _Advanceable =      // exposition only
      /* see definition */;
 
  template<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t>
    requires __WeaklyEqualityComparableWith<W, Bound>
  class iota_view : public view_interface<iota_view<W, Bound>> {
  private:
    // class iota_­view​::​iterator
    struct iterator;            // exposition only
    // class iota_­view​::​sentinel
    struct sentinel;            // exposition only
    W value_ = W();             // exposition only
    Bound bound_ = Bound();     // exposition only
  public:
    iota_view() = default;
    constexpr explicit iota_view(W value);
    constexpr iota_view(type_identity_t<W> value,
                        type_identity_t<Bound> bound);
 
    constexpr iterator begin() const;
    constexpr sentinel end() const;
    constexpr iterator end() const requires Same<W, Bound>;
 
    constexpr auto size() const
      requires (Same<W, Bound> && _Advanceable<W>) ||
               (Integral<W> && Integral<Bound>) ||
               SizedSentinel<Bound, W>
    { return bound_ - value_; }
  };
 
  template<class W, class Bound>
    requires (!Integral<W> || !Integral<Bound> || is_signed_v<W> == is_signed_v<Bound>)
  iota_view(W, Bound) -> iota_view<W, Bound>;
}

Class std::ranges::iota_view::iterator

namespace std::ranges {
  template<class W, class Bound>
  struct iota_view<W, Bound>::iterator {
  private:
    W value_ = W();             // exposition only
  public:
    using iterator_category = /* see definition */;
    using value_type = W;
    using difference_type = iter_difference_t<W>;
 
    iterator() = default;
    constexpr explicit iterator(W value);
 
    constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires Incrementable<W>;
 
    constexpr iterator& operator--() requires _Decrementable<W>;
    constexpr iterator operator--(int) requires _Decrementable<W>;
 
    constexpr iterator& operator+=(difference_type n)
      requires _Advanceable<W>;
    constexpr iterator& operator-=(difference_type n)
      requires _Advanceable<W>;
    constexpr W operator[](difference_type n) const
      requires _Advanceable<W>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires EqualityComparable<W>;
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires EqualityComparable<W>;
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
 
    friend constexpr iterator operator+(iterator i, difference_type n)
      requires _Advanceable<W>;
    friend constexpr iterator operator+(difference_type n, iterator i)
      requires _Advanceable<W>;
 
    friend constexpr iterator operator-(iterator i, difference_type n)
      requires _Advanceable<W>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires _Advanceable<W>;
  };
}

Class std::ranges::iota_view::sentinel

namespace std::ranges {
  template<class W, class Bound>
  struct iota_view<W, Bound>::sentinel {
  private:
    Bound bound_ = Bound();     // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(Bound bound);
 
    friend constexpr bool operator==(const iterator& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator& y);
    friend constexpr bool operator!=(const iterator& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator& y);
  };
}

Class template std::ranges::ref_view

namespace std::ranges {
  template<Range R>
    requires is_object_v<R>
  class ref_view : public view_interface<ref_view<R>> {
  private:
    R* r_ = nullptr;            // exposition only
  public:
    constexpr ref_view() noexcept = default;
 
    template<__NotSameAs<ref_view> T>
      requires /* see definition */
    constexpr ref_view(T&& t);
 
    constexpr R& base() const { return *r_; }
 
    constexpr iterator_t<R> begin() const { return ranges::begin(*r_); }
    constexpr sentinel_t<R> end() const { return ranges::end(*r_); }
 
    constexpr bool empty() const
      requires requires { ranges::empty(*r_); }
    { return ranges::empty(*r_); }
 
    constexpr auto size() const requires SizedRange<R>
    { return ranges::size(*r_); }
 
    constexpr auto data() const requires ContiguousRange<R>
    { return ranges::data(*r_); }
 
    friend constexpr iterator_t<R> begin(ref_view r)
    { return r.begin(); }
 
    friend constexpr sentinel_t<R> end(ref_view r)
    { return r.end(); }
  };
  template<class R>
    ref_view(R&) -> ref_view<R>;
}

Class template std::ranges::filter_view

namespace std::ranges {
  template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred>
    requires View<V> && is_object_v<Pred>
  class filter_view : public view_interface<filter_view<V, Pred>> {
  private:
    V base_ = V();              // exposition only
    semiregular<Pred> pred_;    // exposition only
 
    // class filter_view​::​iterator
    class iterator;             // exposition only
    // class filter_view​::​sentinel
    class sentinel;             // exposition only
 
  public:
    filter_view() = default;
    constexpr filter_view(V base, Pred pred);
    template<InputRange R>
      requires ViewableRange<R> && Constructible<V, all_view<R>>
    constexpr filter_view(R&& r, Pred pred);
 
    constexpr V base() const;
 
    constexpr iterator begin();
    constexpr auto end() {
      if constexpr (CommonRange<V>)
        return iterator{*this, ranges::end(base_)};
      else
        return sentinel{*this};
    }
  };
 
  template<class R, class Pred>
    filter_view(R&&, Pred) -> filter_view<all_view<R>, Pred>;
}

Class std::ranges::filter_view::iterator

namespace std::ranges {
  template<class V, class Pred>
  class filter_view<V, Pred>::iterator {
  private:
    iterator_t<V> current_ = iterator_t<V>();   // exposition only
    filter_view* parent_ = nullptr;             // exposition only
  public:
    using iterator_concept  = /* see definition */;
    using iterator_category = /* see definition */;
    using value_type        = iter_value_t<iterator_t<V>>;
    using difference_type   = iter_difference_t<iterator_t<V>>;
 
    iterator() = default;
    constexpr iterator(filter_view& parent, iterator_t<V> current);
 
    constexpr iterator_t<V> base() const;
    constexpr iter_reference_t<iterator_t<V>> operator*() const;
    constexpr iterator_t<V> operator->() const
      requires has-arrow<iterator_t<V>>;
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires ForwardRange<V>;
 
    constexpr iterator& operator--() requires BidirectionalRange<V>;
    constexpr iterator operator--(int) requires BidirectionalRange<V>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<V>>;
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<V>>;
 
    friend constexpr iter_rvalue_reference_t<iterator_t<V>> iter_move(const iterator& i)
      noexcept(noexcept(ranges::iter_move(i.current_)));
    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
      requires IndirectlySwappable<iterator_t<V>>;
  };
}

Class std::ranges::filter_view::sentinel

namespace std::ranges {
  template<class V, class Pred>
  class filter_view<V, Pred>::sentinel {
  private:
    sentinel_t<V> end_ = sentinel_t<V>();       // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(filter_view& parent);
 
    constexpr sentinel_t<V> base() const;
 
    friend constexpr bool operator==(const iterator& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator& y);
    friend constexpr bool operator!=(const iterator& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator& y);
  };
}

Class template std::ranges::transform_view

namespace std::ranges {
  template<InputRange V, CopyConstructible F>
    requires View<V> && is_object_v<F> &&
             RegularInvocable<F&, iter_reference_t<iterator_t<V>>>
  class transform_view : public view_interface<transform_view<V, F>> {
  private:
    // class template transform_view​::​iterator
    template<bool> struct iterator;             // exposition only
    // class template transform_view​::​sentinel
    template<bool> struct sentinel;             // exposition only
 
    V base_ = V();                              // exposition only
    semiregular<F> fun_;                        // exposition only
 
  public:
    transform_view() = default;
    constexpr transform_view(V base, F fun);
    template<InputRange R>
      requires ViewableRange<R> && Constructible<V, all_view<R>>
    constexpr transform_view(R&& r, F fun);
 
    constexpr V base() const;
 
    constexpr iterator<false> begin();
    constexpr iterator<true> begin() const
      requires Range<const V> &&
               RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
 
    constexpr sentinel<false> end();
    constexpr iterator<false> end() requires CommonRange<V>;
    constexpr sentinel<true> end() const
      requires Range<const V> &&
               RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
    constexpr iterator<true> end() const
      requires CommonRange<const V> &&
               RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
 
    constexpr auto size() requires SizedRange<V> { return ranges::size(base_); }
    constexpr auto size() const requires SizedRange<const V>
    { return ranges::size(base_); }
  };
 
  template<class R, class F>
    transform_view(R&&, F) -> transform_view<all_view<R>, F>;
}

Class template std::ranges::transform_view::iterator

namespace std::ranges {
  template<class V, class F>
  template<bool Const>
  class transform_view<V, F>::iterator {
  private:
    using Parent =                              // exposition only
      conditional_t<Const, const transform_view, transform_view>;
    using Base   =                              // exposition only
      conditional_t<Const, const V, V>;
    iterator_t<Base> current_ =                 // exposition only
      iterator_t<Base>();
    Parent* parent_ = nullptr;                  // exposition only
  public:
    using iterator_concept  = /* see definition */;
    using iterator_category = /* see definition */;
    using value_type        =
      remove_cvref_t<invoke_result_t<F&, iter_reference_t<iterator_t<Base>>>>;
    using difference_type   = iter_difference_t<iterator_t<Base>>;
 
    iterator() = default;
    constexpr iterator(Parent& parent, iterator_t<Base> current);
    constexpr iterator(iterator<!Const> i)
      requires Const && ConvertibleTo<iterator_t<V>, iterator_t<Base>>;
 
    constexpr iterator_t<Base> base() const;
    constexpr decltype(auto) operator*() const
    { return invoke(*parent_->fun_, *current_); }
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires ForwardRange<Base>;
 
    constexpr iterator& operator--() requires BidirectionalRange<Base>;
    constexpr iterator operator--(int) requires BidirectionalRange<Base>;
 
    constexpr iterator& operator+=(difference_type n)
      requires RandomAccessRange<Base>;
    constexpr iterator& operator-=(difference_type n)
      requires RandomAccessRange<Base>;
    constexpr decltype(auto) operator[](difference_type n) const
      requires RandomAccessRange<Base>
    { return invoke(*parent_->fun_, current_[n]); }
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<Base>>;
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<Base>>;
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires RandomAccessRange<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires RandomAccessRange<Base>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires RandomAccessRange<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires RandomAccessRange<Base>;
 
    friend constexpr iterator operator+(iterator i, difference_type n)
      requires RandomAccessRange<Base>;
    friend constexpr iterator operator+(difference_type n, iterator i)
      requires RandomAccessRange<Base>;
 
    friend constexpr iterator operator-(iterator i, difference_type n)
      requires RandomAccessRange<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires RandomAccessRange<Base>;
 
    friend constexpr decltype(auto) iter_move(const iterator& i)
      noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
    {
      if constexpr (is_lvalue_reference_v<decltype(*i)>)
        return std::move(*i);
      else
        return *i;
    }
 
    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
      requires IndirectlySwappable<iterator_t<Base>>;
  };
}

Class template std::ranges::transform_view::sentinel

namespace std::ranges {
  template<class V, class F>
  template<bool Const>
  class transform_view<V, F>::sentinel {
  private:
    using Parent =                                      // exposition only
      conditional_t<Const, const transform_view, transform_view>;
    using Base = conditional_t<Const, const V, V>;      // exposition only
    sentinel_t<Base> end_ = sentinel_t<Base>();         // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end);
    constexpr sentinel(sentinel<!Const> i)
      requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;
 
    constexpr sentinel_t<Base> base() const;
 
    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y);
    friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y);
 
    friend constexpr iter_difference_t<iterator_t<Base>>
      operator-(const iterator<Const>& x, const sentinel& y)
        requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>;
    friend constexpr iter_difference_t<iterator_t<Base>>
      operator-(const sentinel& y, const iterator<Const>& x)
        requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>;
  };
}

Class template std::ranges::take_view

namespace std::ranges {
  template<View V>
  class take_view : public view_interface<take_view<V>> {
  private:
    V base_ = V();                                      // exposition only
    iter_difference_t<iterator_t<V>> count_ = 0;        // exposition only
    // class template take_­view​::​sentinel
    template<bool> struct sentinel;                     // exposition only
  public:
    take_view() = default;
    constexpr take_view(V base, iter_difference_t<iterator_t<V>> count);
    template<ViewableRange R>
      requires Constructible<V, all_view<R>>
    constexpr take_view(R&& r, iter_difference_t<iterator_t<V>> count);
 
    constexpr V base() const;
 
    constexpr auto begin() requires (!__SimpleView<V>) {
      if constexpr (SizedRange<V>) {
        if constexpr (RandomAccessRange<V>)
          return ranges::begin(base_);
        else
          return counted_iterator{ranges::begin(base_), size()};
      } else
        return counted_iterator{ranges::begin(base_), count_};
    }
 
    constexpr auto begin() const requires Range<const V> {
      if constexpr (SizedRange<const V>) {
        if constexpr (RandomAccessRange<const V>)
          return ranges::begin(base_);
        else
          return counted_iterator{ranges::begin(base_), size()};
      } else
        return counted_iterator{ranges::begin(base_), count_};
    }
 
    constexpr auto end() requires (!__SimpleView<V>) {
      if constexpr (SizedRange<V>) {
        if constexpr (RandomAccessRange<V>)
          return ranges::begin(base_) + size();
        else
          return default_sentinel;
      } else
        return sentinel<false>{ranges::end(base_)};
    }
 
    constexpr auto end() const requires Range<const V> {
      if constexpr (SizedRange<const V>) {
        if constexpr (RandomAccessRange<const V>)
          return ranges::begin(base_) + size();
        else
          return default_sentinel;
      } else
        return sentinel<true>{ranges::end(base_)};
    }
 
    constexpr auto size() requires SizedRange<V> {
      auto n = ranges::size(base_);
      return ranges::min(n, static_cast<decltype(n)>(count_));
    }
 
    constexpr auto size() const requires SizedRange<const V> {
      auto n = ranges::size(base_);
      return ranges::min(n, static_cast<decltype(n)>(count_));
    }
  };
 
  template<Range R>
    take_view(R&&, iter_difference_t<iterator_t<R>>)
      -> take_view<all_view<R>>;
}

Class template std::ranges::take_view::sentinel

namespace std::ranges {
  template<class V>
  template<bool Const>
  class take_view<V>::sentinel {
  private:
    using Base = conditional_t<Const, const V, V>;      // exposition only
    using CI = counted_iterator<iterator_t<Base>>;      // exposition only
    sentinel_t<Base> end_ = sentinel_t<Base>();         // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end);
    constexpr sentinel(sentinel<!Const> s)
      requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;
 
    constexpr sentinel_t<Base> base() const;
 
    friend constexpr bool operator==(const sentinel& x, const CI& y);
    friend constexpr bool operator==(const CI& y, const sentinel& x);
    friend constexpr bool operator!=(const sentinel& x, const CI& y);
    friend constexpr bool operator!=(const CI& y, const sentinel& x);
  };
}

Class template std::ranges::join_view

namespace std::ranges {
  template<InputRange V>
    requires View<V> && InputRange<iter_reference_t<iterator_t<V>>> &&
             (is_reference_v<iter_reference_t<iterator_t<V>>> ||
              View<iter_value_t<iterator_t<V>>>)
  class join_view : public view_interface<join_view<V>> {
  private:
    using InnerRng =                    // exposition only
      iter_reference_t<iterator_t<V>>;
    // class template join_­view​::​iterator
    template<bool Const>
      struct iterator;                  // exposition only
    // class template join_­view​::​sentinel
    template<bool Const>
      struct sentinel;                  // exposition only
 
    V base_ = V();                      // exposition only
    all_view<InnerRng> inner_ =         // exposition only, present only when
      all_view<InnerRng>();              // !is_reference_v<InnerRng>
  public:
    join_view() = default;
    constexpr explicit join_view(V base);
 
    template<InputRange R>
      requires ViewableRange<R> && Constructible<V, all_view<R>>
    constexpr explicit join_view(R&& r);
 
    constexpr auto begin() {
      return iterator<__SimpleView<V>>{*this, ranges::begin(base_)};
    }
 
    constexpr auto begin() const
    requires InputRange<const V> &&
             is_reference_v<iter_reference_t<iterator_t<const V>>> {
      return iterator<true>{*this, ranges::begin(base_)};
    }
 
    constexpr auto end() {
      if constexpr (ForwardRange<V> &&
                    is_reference_v<InnerRng> && ForwardRange<InnerRng> &&
                    CommonRange<V> && CommonRange<InnerRng>)
        return iterator<__SimpleView<V>>{*this, ranges::end(base_)};
      else
        return sentinel<__SimpleView<V>>{*this};
    }
 
    constexpr auto end() const
    requires InputRange<const V> &&
             is_reference_v<iter_reference_t<iterator_t<const V>>> {
      if constexpr (ForwardRange<const V> &&
                    is_reference_v<iter_reference_t<iterator_t<const V>>> &&
                    ForwardRange<iter_reference_t<iterator_t<const V>>> &&
                    CommonRange<const V> &&
                    CommonRange<iter_reference_t<iterator_t<const V>>>)
        return iterator<true>{*this, ranges::end(base_)};
      else
        return sentinel<true>{*this};
    }
  };
 
  template<class R>
    explicit join_view(R&&) -> join_view<all_view<R>>;
}

Class template std::ranges::join_view::iterator

namespace std::ranges {
template<class V>
  template<bool Const>
  struct join_view<V>::iterator {
  private:
    using Parent =                                              // exposition only
      conditional_t<Const, const join_view, join_view>;
    using Base   = conditional_t<Const, const V, V>;            // exposition only
 
    static constexpr bool ref_is_glvalue =                      // exposition only
      is_reference_v<iter_reference_t<iterator_t<Base>>>;
 
    iterator_t<Base> outer_ = iterator_t<Base>();               // exposition only
    iterator_t<iter_reference_t<iterator_t<Base>>> inner_ =     // exposition only
      iterator_t<iter_reference_t<iterator_t<Base>>>();
    Parent* parent_ = nullptr;                                  // exposition only
 
    constexpr void satisfy();                                   // exposition only
  public:
    using iterator_concept  = /* see definition */;
    using iterator_category = /* see definition */;
    using value_type        =
      iter_value_t<iterator_t<iter_reference_t<iterator_t<Base>>>>;
    using difference_type   = /* see definition */;
 
    iterator() = default;
    constexpr iterator(Parent& parent, iterator_t<V> outer);
    constexpr iterator(iterator<!Const> i)
      requires Const &&
               ConvertibleTo<iterator_t<V>, iterator_t<Base>> &&
               ConvertibleTo<iterator_t<InnerRng>,
                             iterator_t<iter_reference_t<iterator_t<Base>>>>;
 
    constexpr decltype(auto) operator*() const { return *inner_; }
 
    constexpr iterator_t<Base> operator->() const
      requires __HasArrow<iterator_t<Base>>;
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int)
      requires ref_is_glvalue && ForwardRange<Base> &&
               ForwardRange<iter_reference_t<iterator_t<Base>>>;
 
    constexpr iterator& operator--()
      requires ref_is_glvalue && BidirectionalRange<Base> &&
               BidirectionalRange<iter_reference_t<iterator_t<Base>>>;
 
    constexpr iterator operator--(int)
      requires ref_is_glvalue && BidirectionalRange<Base> &&
               BidirectionalRange<iter_reference_t<iterator_t<Base>>>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> &&
               EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>;
 
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> &&
               EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>;
 
    friend constexpr decltype(auto) iter_move(const iterator& i)
    noexcept(noexcept(ranges::iter_move(i.inner_))) {
      return ranges::iter_move(i.inner_);
    }
 
    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
  };
}

Class template std::ranges::join_view::sentinel

namespace std::ranges {
  template<class V>
  template<bool Const>
  struct join_view<V>::sentinel {
  private:
    using Parent =                                      // exposition only
      conditional_t<Const, const join_view, join_view>;
    using Base   = conditional_t<Const, const V, V>;    // exposition only
    sentinel_t<Base> end_ = sentinel_t<Base>();         // exposition only
  public:
    sentinel() = default;
 
    constexpr explicit sentinel(Parent& parent);
    constexpr sentinel(sentinel<!Const> s)
      requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;
 
    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y);
    friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y);
  };
}

Class template std::ranges::split_­view

namespace std::ranges {
  template<auto> struct __require_constant;     // exposition only
 
  template<class R>
  concept __TinyRange =                         // exposition only
    SizedRange<R> &&
    requires { typename __require_constant<remove_reference_t<R>::size()>; } &&
    (remove_reference_t<R>::size() <= 1);
 
  template<InputRange V, ForwardRange Pattern>
    requires View<V> && View<Pattern> &&
             IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (ForwardRange<V> || __TinyRange<Pattern>)
  class split_view : public view_interface<split_view<V, Pattern>> {
  private:
    V base_ = V();                              // exposition only
    Pattern pattern_ = Pattern();               // exposition only
    iterator_t<V> current_ = iterator_t<V>();   // exposition only, present only if 
                                                // !ForwardRange<V>
    // class template split_­view​::​outer_­iterator
    template<bool> struct outer_iterator;       // exposition only
    // class template split_­view​::​inner_­iterator
    template<bool> struct inner_iterator;       // exposition only
  public:
    split_view() = default;
    constexpr split_view(V base, Pattern pattern);
 
    template<InputRange R, ForwardRange P>
      requires Constructible<V, all_view<R>> &&
               Constructible<Pattern, all_view<P>>
    constexpr split_view(R&& r, P&& p);
 
    template<InputRange R>
      requires Constructible<V, all_view<R>> &&
               Constructible<Pattern, single_view<iter_value_t<iterator_t<R>>>>
    constexpr split_view(R&& r, iter_value_t<iterator_t<R>> e);
 
    constexpr auto begin() {
      if constexpr (ForwardRange<V>)
        return outer_iterator<__SimpleView<V>>{*this, ranges::begin(base_)};
      else {
        current_ = ranges::begin(base_);
        return outer_iterator<false>{*this};
      }
    }
 
    constexpr auto begin() const requires ForwardRange<V> && ForwardRange<const V> {
      return outer_iterator<true>{*this, ranges::begin(base_)};
    }
 
    constexpr auto end() requires ForwardRange<V> && CommonRange<V> {
      return outer_iterator<__SimpleView<V>>{*this, ranges::end(base_)};
    }
 
    constexpr auto end() const {
      if constexpr (ForwardRange<V> && ForwardRange<const V> && CommonRange<const V>)
        return outer_iterator<true>{*this, ranges::end(base_)};
      else
        return default_sentinel;
    }
  };
 
  template<class R, class P>
    split_view(R&&, P&&) -> split_view<all_view<R>, all_view<P>>;
 
  template<InputRange R>
    split_view(R&&, iter_value_t<iterator_t<R>>)
      -> split_view<all_view<R>, single_view<iter_value_t<iterator_t<R>>>>;
}

Class template std::ranges::split_view::outer_iterator

namespace std::ranges {
  template<class V, class Pattern>
  template<bool Const>
  struct split_view<V, Pattern>::outer_iterator {
  private:
    using Parent =                              // exposition only
      conditional_t<Const, const split_view, split_view>;
    using Base   =                              // exposition only
      conditional_t<Const, const V, V>;
    Parent* parent_ = nullptr;                  // exposition only
    iterator_t<Base> current_ =                 // exposition only, present only
      iterator_t<Base>();                       // if V models ForwardRange
 
  public:
    using iterator_concept  =
      conditional_t<ForwardRange<Base>, forward_iterator_tag, input_iterator_tag>;
    using iterator_category = input_iterator_tag;
    struct value_type;
    using difference_type   = iter_difference_t<iterator_t<Base>>;
 
    outer_iterator() = default;
    constexpr explicit outer_iterator(Parent& parent)
      requires (!ForwardRange<Base>);
    constexpr outer_iterator(Parent& parent, iterator_t<Base> current)
      requires ForwardRange<Base>;
    constexpr outer_iterator(outer_iterator<!Const> i)
      requires Const && ConvertibleTo<iterator_t<V>, iterator_t<const V>>;
 
    constexpr value_type operator*() const;
 
    constexpr outer_iterator& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (ForwardRange<Base>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }
 
    friend constexpr bool operator==(const outer_iterator& x, const outer_iterator& y)
      requires ForwardRange<Base>;
    friend constexpr bool operator!=(const outer_iterator& x, const outer_iterator& y)
      requires ForwardRange<Base>;
 
    friend constexpr bool operator==(const outer_iterator& x, default_sentinel_t);
    friend constexpr bool operator==(default_sentinel_t, const outer_iterator& x);
    friend constexpr bool operator!=(const outer_iterator& x, default_sentinel_t y);
    friend constexpr bool operator!=(default_sentinel_t y, const outer_iterator& x);
  };
}

Class std::ranges::split_view::outer_iterator::value_type

namespace std::ranges {
  template<class V, class Pattern>
  template<bool Const>
  struct split_view<V, Pattern>::outer_iterator<Const>::value_type {
  private:
    outer_iterator i_ = outer_iterator();               // exposition only
  public:
    value_type() = default;
    constexpr explicit value_type(outer_iterator i);
 
    constexpr inner_iterator<Const> begin() const;
    constexpr default_sentinel_t end() const;
  };
}

Class template std::ranges::split_view::inner_iterator

namespace std::ranges {
  template<class V, class Pattern>
  template<bool Const>
  struct split_view<V, Pattern>::inner_iterator {
  private:
    using Base =
      conditional_t<Const, const V, V>;                 // exposition only
    outer_iterator<Const> i_ = outer_iterator<Const>(); // exposition only
    bool incremented_ = false;                          // exposition only
  public:
    using iterator_concept  = typename outer_iterator<Const>::iterator_concept;
    using iterator_category = /* see definition */;
    using value_type        = iter_value_t<iterator_t<Base>>;
    using difference_type   = iter_difference_t<iterator_t<Base>>;
 
    inner_iterator() = default;
    constexpr explicit inner_iterator(outer_iterator<Const> i);
 
    constexpr decltype(auto) operator*() const { return *i_.current; }
 
    constexpr inner_iterator& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (ForwardRange<V>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }
 
    friend constexpr bool operator==(const inner_iterator& x, const inner_iterator& y)
      requires ForwardRange<Base>;
    friend constexpr bool operator!=(const inner_iterator& x, const inner_iterator& y)
      requires ForwardRange<Base>;
 
    friend constexpr bool operator==(const inner_iterator& x, default_sentinel_t);
    friend constexpr bool operator==(default_sentinel_t, const inner_iterator& x);
    friend constexpr bool operator!=(const inner_iterator& x, default_sentinel_t y);
    friend constexpr bool operator!=(default_sentinel_t y, const inner_iterator& x);
 
    friend constexpr decltype(auto) iter_move(const inner_iterator& i)
    noexcept(noexcept(ranges::iter_move(i.i_.current))) {
      return ranges::iter_move(i.i_.current);
    }
 
    friend constexpr void iter_swap(const inner_iterator& x, const inner_iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
      requires IndirectlySwappable<iterator_t<Base>>;
  };
}

Class template std::ranges::common_view

namespace std::ranges {
  template<View V>
    requires (!CommonRange<V>)
  class common_view : public view_interface<common_view<V>> {
  private:
    V base_ = V();  // exposition only
  public:
    common_view() = default;
 
    constexpr explicit common_view(V r);
 
    template<ViewableRange R>
      requires (!CommonRange<R> && Constructible<V, all_view<R>>)
    constexpr explicit common_view(R&& r);
 
    constexpr V base() const;
 
    constexpr auto size() requires SizedRange<V> {
      return ranges::size(base_);
    }
    constexpr auto size() const requires SizedRange<const V> {
      return ranges::size(base_);
    }
 
    constexpr auto begin() {
      if constexpr (RandomAccessRange<V> && SizedRange<V>)
        return ranges::begin(base_);
      else
        return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
    }
 
    constexpr auto begin() const requires Range<const V> {
      if constexpr (RandomAccessRange<const V> && SizedRange<const V>)
        return ranges::begin(base_);
      else
        return
          common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
    }
 
    constexpr auto end() {
      if constexpr (RandomAccessRange<V> && SizedRange<V>)
        return ranges::begin(base_) + ranges::size(base_);
      else
        return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
    }
 
    constexpr auto end() const requires Range<const V> {
      if constexpr (RandomAccessRange<const V> && SizedRange<const V>)
        return ranges::begin(base_) + ranges::size(base_);
      else
        return
          common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
    }
  };
 
  template<class R>
    common_view(R&&) -> common_view<all_view<R>>;
}

Class template std::ranges::reverse_view

namespace std::ranges {
  template<View V>
    requires BidirectionalRange<V>
  class reverse_view : public view_interface<reverse_view<V>> {
  private:
    V base_ = V();  // exposition only
  public:
    reverse_view() = default;
 
    constexpr explicit reverse_view(V r);
 
    template<ViewableRange R>
      requires BidirectionalRange<R> && Constructible<V, all_view<R>>
    constexpr explicit reverse_view(R&& r);
 
    constexpr V base() const;
 
    constexpr reverse_iterator<iterator_t<V>> begin();
    constexpr reverse_iterator<iterator_t<V>> begin() requires CommonRange<V>;
    constexpr reverse_iterator<iterator_t<const V>> begin() const
      requires CommonRange<const V>;
 
    constexpr reverse_iterator<iterator_t<V>> end();
    constexpr reverse_iterator<iterator_t<const V>> end() const
      requires CommonRange<const V>;
 
    constexpr auto size() requires SizedRange<V> {
      return ranges::size(base_);
    }
    constexpr auto size() const requires SizedRange<const V> {
      return ranges::size(base_);
    }
  };
 
  template<class R>
    reverse_view(R&&) -> reverse_view<all_view<R>>;
}

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/header/ranges