#include <initializer_list> #include <iterator> namespace std::ranges { inline namespace unspecified { // [range.access], 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; } // [range.range], ranges template<class T> using iterator_t = decltype(ranges::begin(declval<T&>())); template<class T> using sentinel_t = decltype(ranges::end(declval<T&>())); template<forwarding-range R> using safe_iterator_t = iterator_t<R>; template<class T> concept Range = see below; // [range.sized], sized ranges template<class> inline constexpr bool disable_sized_range = false; template<class T> concept SizedRange = see below; // [range.view], views template<class T> inline constexpr bool enable_view = see below; struct view_base { }; template<class T> concept View = see below; // [range.refinements], other range refinements template<class R, class T> concept OutputRange = see below; template<class T> concept InputRange = see below; template<class T> concept ForwardRange = see below; template<class T> concept BidirectionalRange = see below; template<class T> concept RandomAccessRange = see below; template<class T> concept ContiguousRange = see below; template<class T> concept CommonRange = see below; template<class T> concept ViewableRange = see below; // [view.interface], class template view_interface template<class D> requires is_class_v<D> && Same<D, remove_cv_t<D>> class view_interface; // [range.subrange], sub-ranges enum class subrange_kind : bool { unsized, sized }; template<Iterator I, Sentinel<I> S = I, subrange_kind K = see below> requires (K == subrange_kind::sized || !SizedSentinel<S, I>) class subrange; template<forwarding-range R> using safe_subrange_t = subrange<iterator_t<R>>; // [range.empty], empty view template<class T> requires is_object_v<T> class empty_view; namespace view { template<class T> inline constexpr empty_view<T> empty{}; } // [range.single], single view template<CopyConstructible T> requires is_object_v<T> class single_view; namespace view { inline constexpr unspecified single = unspecified; } // [range.iota], iota view template<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t> requires weakly-equality-comparable-with<W, Bound> class iota_view; namespace view { inline constexpr unspecified iota = unspecified; } // [range.all], all view namespace view { inline constexpr unspecified all = unspecified; } template<ViewableRange R> using all_view = decltype(view::all(declval<R>())); // [range.filter], 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; } // [range.transform], 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; } // [range.take], take view template<View> class take_view; namespace view { inline constexpr unspecified take = unspecified; } // [range.join], 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; } // [range.split], split view template<class R> concept tiny-range = see below; // exposition only template<InputRange V, ForwardRange Pattern> requires View<V> && View<Pattern> && IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to<>> && (ForwardRange<V> || tiny-range<Pattern>) class split_view; namespace view { inline constexpr unspecified split = unspecified; } // [range.counted], counted view namespace view { inline constexpr unspecified counted = unspecified; } // [range.common], common view template<View V> requires (!CommonRange<V>) class common_view; namespace view { inline constexpr unspecified common = unspecified; } // [range.reverse], 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; }; }
template<class T> void begin(T&&) = delete; template<class T> void begin(initializer_list<T>&&) = delete;and does not include a declaration of ranges::begin.
template<class T> void end(T&&) = delete; template<class T> void end(initializer_list<T>&&) = delete;and does not include a declaration of ranges::end.
template<class T> void rbegin(T&&) = delete;and does not include a declaration of ranges::rbegin.
template<class T> void rend(T&&) = delete;and does not include a declaration of ranges::rend.
template<class T> void size(T&&) = delete;and does not include a declaration of ranges::size.
template<class T>
concept range-impl = // exposition only
requires(T&& t) {
ranges::begin(std::forward<T>(t)); // sometimes equality-preserving (see below)
ranges::end(std::forward<T>(t));
};
template<class T>
concept Range = range-impl<T&>;
template<class T>
concept forwarding-range = // exposition only
Range<T> && range-impl<T>;
template<class T>
concept SizedRange =
Range<T> &&
!disable_sized_range<remove_cvref_t<T>> &&
requires(T& t) { ranges::size(t); };
template<class T>
inline constexpr bool enable_view = see below;
template<class T>
concept View =
Range<T> && Semiregular<T> && enable_view<T>;
template<class R, class T>
concept OutputRange =
Range<R> && OutputIterator<iterator_t<R>, T>;
template<class T>
concept InputRange =
Range<T> && InputIterator<iterator_t<T>>;
template<class T>
concept ForwardRange =
InputRange<T> && ForwardIterator<iterator_t<T>>;
template<class T>
concept BidirectionalRange =
ForwardRange<T> && BidirectionalIterator<iterator_t<T>>;
template<class T>
concept RandomAccessRange =
BidirectionalRange<T> && RandomAccessIterator<iterator_t<T>>;
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>>>>;
};
template<class T>
concept CommonRange =
Range<T> && Same<iterator_t<T>, sentinel_t<T>>;
template<class T>
concept ViewableRange =
Range<T> && (forwarding-range<T> || View<decay_t<T>>);
template<class R> concept simple-view = // 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 has-arrow = // exposition only is_pointer_v<I> || requires(I i) { i.operator->(); }; template<class T, class U> concept not-same-as = // exposition only !Same<remove_cvref_t<T>, remove_cvref_t<U>>;
namespace std::ranges { template<Range R> struct range-common-iterator-impl { // exposition only using type = common_iterator<iterator_t<R>, sentinel_t<R>>; }; template<CommonRange R> struct range-common-iterator-impl<R> { // exposition only using type = iterator_t<R>; }; template<Range R> using range-common-iterator = // exposition only typename range-common-iterator-impl<R>::type; 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]; } }; }
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>;
namespace std::ranges { template<class T> concept pair-like = // 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 pair-like-convertible-to = // exposition only !Range<T> && pair-like<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 pair-like-convertible-from = // exposition only !Range<T> && pair-like<T> && Constructible<T, U, V>; template<class T> concept iterator-sentinel-pair = // exposition only !Range<T> && pair-like<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<not-same-as<subrange> R> requires forwarding-range<R> && ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S> constexpr subrange(R&& r) requires (!StoreSize || SizedRange<R>); template<forwarding-range 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<not-same-as<subrange> PairLike> requires pair-like-convertible-to<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<pair-like-convertible-to<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<not-same-as<subrange> PairLike> requires pair-like-convertible-from<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<iterator-sentinel-pair P> subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>; template<iterator-sentinel-pair 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<forwarding-range 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<forwarding-range 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; }
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<not-same-as<subrange> R>
requires forwarding-range<R> &&
ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S>
constexpr subrange(R&& r) requires (!StoreSize || SizedRange<R>);
template<not-same-as<subrange> PairLike>
requires pair-like-convertible-from<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);
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::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; } }; }
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; }; }
constexpr explicit single_view(const T& t);
constexpr explicit single_view(T&& t);
template<class... 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;
namespace std::ranges { template<class I> concept Decrementable = // exposition only see below; template<class I> concept Advanceable = // exposition only see below; template<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t> requires weakly-equality-comparable-with<W, Bound> class iota_view : public view_interface<iota_view<W, Bound>> { private: struct iterator; // exposition only 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>; }
template<class I>
concept Decrementable =
Incrementable<I> && requires(I i) {
{ --i } -> Same<I&>;
{ i-- } -> Same<I>;
};
template<class I>
concept Advanceable =
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>>;
};
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>;
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 below; 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>; }; }
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>;
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); }; }
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);
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 | view::filter(even) | view::transform(square)) { cout << i << ' '; // prints: 0 4 16 } assert(ranges::equal(ints | view::filter(even), view::filter(ints, even)));— end example
C(R) R | C
R | C | D R | (C | D)
constexpr semiregular() noexcept(is_nothrow_default_constructible_v<T>) : semiregular{in_place} { }
semiregular& operator=(const semiregular& that) noexcept(is_nothrow_copy_constructible_v<T>) { if (that) emplace(*that); else reset(); return *this; }
semiregular& operator=(semiregular&& that) noexcept(is_nothrow_move_constructible_v<T>) { if (that) emplace(std::move(*that)); else reset(); return *this; }
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<not-same-as<ref-view> T> requires see below 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<not-same-as<ref-view> T>
requires see below
constexpr ref-view(T&& t);
void FUN(R&); void FUN(R&&) = delete;
ConvertibleTo<T, R&> && requires { FUN(declval<T>()); }
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 iterator; // exposition only 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>; }
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();
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 below; using iterator_category = see below; 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>>; }; }
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++();
current_ = ranges::find_if(++current_, ranges::end(parent_->base_), ref(*parent_->pred_)); return *this;
constexpr void operator++(int);
constexpr iterator operator++(int) requires ForwardRange<V>;
constexpr iterator& operator--() requires BidirectionalRange<V>;
do --current_; while (!invoke(*parent_->pred_, *current_)); return *this;
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>>;
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); }; }
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);
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: template<bool> struct iterator; // exposition only 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>; }
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>>>;
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 below; using iterator_category = see below; 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>>; }; }
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 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>;
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 void iter_swap(const iterator& x, const iterator& y)
noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
requires IndirectlySwappable<iterator_t<Base>>;
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>>; }; }
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>>;
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 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 (!simple-view<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 (!simple-view<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>>; }
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;
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); }; }
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);
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>>; template<bool Const> struct iterator; // exposition only template<bool Const> struct sentinel; // exposition only V base_ = V(); // exposition only all_view<InnerRng> inner_ = // exposition only, present only when !is_reference_v<InnerRng> all_view<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<simple-view<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<simple-view<V>>{*this, ranges::end(base_)}; else return sentinel<simple-view<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>>; }
constexpr explicit join_view(V base);
template<InputRange R>
requires ViewableRange<R> && Constructible<V, all_view<R>>
constexpr explicit join_view(R&& r);
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 below; using iterator_category = see below; using value_type = iter_value_t<iterator_t<iter_reference_t<iterator_t<Base>>>>; using difference_type = see below; 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 has-arrow<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_))); }; }
common_type_t< iter_difference_t<iterator_t<Base>>, iter_difference_t<iterator_t<iter_reference_t<iterator_t<Base>>>>>
constexpr void satisfy(); // exposition only
auto update_inner = [this](iter_reference_t<iterator_t<Base>> x) -> decltype(auto) { if constexpr (ref_is_glvalue) // x is a reference return (x); // (x) is an lvalue else return (parent_->inner_ = view::all(x)); }; for (; outer_ != ranges::end(parent_->base_); ++outer_) { auto& inner = update_inner(*outer_); inner_ = ranges::begin(inner); if (inner_ != ranges::end(inner)) return; } if constexpr (ref_is_glvalue) inner_ = iterator_t<iter_reference_t<iterator_t<Base>>>();
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 iterator_t<Base> operator->() const
requires has-arrow<iterator_t<Base>>;
constexpr iterator& operator++();
auto&& inner_rng = inner-range; if (++inner_ == ranges::end(inner_rng)) { ++outer_; satisfy(); } return *this;
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>>>;
if (outer_ == ranges::end(parent_->base_)) inner_ = ranges::end(*--outer_); while (inner_ == ranges::begin(*outer_)) inner_ = ranges::end(*--outer_); --inner_; return *this;
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 void iter_swap(const iterator& x, const iterator& y)
noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
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); }; }
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);
namespace std::ranges { template<auto> struct require-constant; // exposition only template<class R> concept tiny-range = // 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> || tiny-range<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> template<bool> struct outer_iterator; // exposition only 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<simple-view<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<simple-view<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>>>>; }
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);
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 if V models ForwardRange iterator_t<Base>(); public: using iterator_concept = conditional_t<ForwardRange<Base>, forward_iterator_tag, input_iterator_tag>; using iterator_category = input_iterator_tag; struct value_type; // see [range.split.outer.value] 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); }; }
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++();
const auto end = ranges::end(parent_->base_); if (current == end) return *this; const auto [pbegin, pend] = subrange{parent_->pattern_}; if (pbegin == pend) ++current; else { do { const auto [b, p] = ranges::mismatch(current, end, pbegin, pend); if (p == pend) { current = b; // The pattern matched; skip it break; } } while (++current != end); } return *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);
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; }; }
constexpr explicit value_type(outer_iterator i);
constexpr inner_iterator<Const> begin() const;
constexpr default_sentinel_t end() const;
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 below; 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>>; }; }
constexpr explicit inner_iterator(outer_iterator<Const> i);
constexpr inner_iterator& operator++() const;
incremented_ = true; if constexpr (!ForwardRange<Base>) { if constexpr (Pattern::size() == 0) { return *this; } } ++i_.current; return *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);
auto cur = x.i_.current; auto end = ranges::end(x.i_.parent_->base_); if (cur == end) return true; auto [pcur, pend] = subrange{x.i_.parent_->pattern_}; if (pcur == pend) return x.incremented_; do { if (*cur != *pcur) return false; if (++pcur == pend) return true; } while (++cur != end); return false;
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 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>>;
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>>; }
constexpr explicit common_view(V base);
template<ViewableRange R>
requires (!CommonRange<R> && Constructible<V, all_view<R>>)
constexpr explicit common_view(R&& r);
constexpr V base() const;
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>>; }
constexpr explicit reverse_view(V base);
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>;