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>;