Standard library header <ranges>
From cppreference.com
This header is part of the ranges library.
Namespace aliases
namespace std { namespace view = ranges::view; |
||
The namespace alias std::view
is provided as a shorthand for std::ranges::view
.
Concepts | |
Range concepts | |
Defined in namespace
std::ranges | |
specifies that a type is a range, that is, it provides a begin iterator and an end sentinel (concept) | |
specifies that a range knows its size in constant time (concept) | |
specifies that a range is a view, that is, it has constant time copy/move/assignment (concept) | |
specifies a range whose iterator type satisfies InputIterator (concept) | |
specifies a range whose iterator type satisfies OutputIterator (concept) | |
specifies a range whose iterator type satisfies ForwardIterator (concept) | |
specifies a range whose iterator type satisfies BidirectionalIterator (concept) | |
specifies a range whose iterator type satisfies RandomAccessIterator (concept) | |
specifies a range whose iterator type satisfies ContiguousIterator (concept) | |
specifies that a range has identical iterator and sentinel types (concept) | |
specifies the requirements for a Range to be safely convertible to a View (concept) | |
Classes | |
Range primitives | |
Defined in namespace
std::ranges | |
obtains the iterator and sentinel types of a range (alias template) | |
Views | |
Defined in namespace
std::ranges | |
helper class template for defining View s, using the curiously recurring template pattern (class template) | |
combines an iterator-sentinel pair into a View (class template) | |
Dangling iterator handling | |
Defined in namespace
std::ranges | |
a placeholder type indicating that an iterator or a subrange should not be returned since it would be dangling (class) | |
obtains iterator type or subrange type of a Range which also models __ForwardingRange (alias template) | |
Factories | |
Defined in namespace
std::ranges | |
an empty View with no elements (class template) (variable template) | |
a View that contains a single element of a specified value (class template) (customization point object) | |
a View consisting of a sequence generated by repeatedly incrementing an initial value (class template) (customization point object) | |
creates a subrange from an iterator and a count (customization point object) | |
Adaptors | |
Defined in namespace
std::ranges | |
a View that includes all elements of a Range (alias template) (range adaptor object) | |
a View of the elements of some other Range (class template) | |
a View that consists of the elements of a Range that satisfies a predicate (class template) (range adaptor object) | |
a View of a sequence that applies a transformation function to each element (class template) (range adaptor object) | |
a View consisting of the first N elements of another View (class template) (range adaptor object) | |
a View consisting of the sequence obtained from flattening a View of Range s (class template) (range adaptor object) | |
a View over the subranges obtained from splitting another View using a delimiter (class template) (range adaptor object) | |
converts a View into a CommonRange (class template) (range adaptor object) | |
a View that iterates over the elements of another bidirectional view in reverse order (class template) (range adaptor object) | |
Customization point objects | |
Range access | |
Defined in namespace
std::ranges | |
returns an iterator to the beginning of a range (customization point object) | |
returns an iterator to the end of a range (customization point object) | |
returns a reverse iterator to a range (customization point object) | |
returns a reverse end iterator to a range (customization point object) | |
obtains the size of a range whose size can be calculated in constant time (customization point object) | |
checks whether a range is empty (customization point object) | |
obtains a pointer to the beginning of a contiguous range (customization point object) |
Synopsis
#include <initializer_list> #include <iterator> namespace std::ranges { inline namespace /* unspecified */ { // range access inline constexpr /* unspecified */ begin = /* unspecified */; inline constexpr /* unspecified */ end = /* unspecified */; inline constexpr /* unspecified */ cbegin = /* unspecified */; inline constexpr /* unspecified */ cend = /* unspecified */; inline constexpr /* unspecified */ rbegin = /* unspecified */; inline constexpr /* unspecified */ rend = /* unspecified */; inline constexpr /* unspecified */ crbegin = /* unspecified */; inline constexpr /* unspecified */ crend = /* unspecified */; inline constexpr /* unspecified */ size = /* unspecified */; inline constexpr /* unspecified */ empty = /* unspecified */; inline constexpr /* unspecified */ data = /* unspecified */; inline constexpr /* unspecified */ cdata = /* unspecified */; } // ranges template<class T> using iterator_t = decltype(ranges::begin(declval<T&>())); template<class T> using sentinel_t = decltype(ranges::end(declval<T&>())); template<class T> concept Range = /* see definition */; // sized ranges template<class> inline constexpr bool disable_sized_range = false; template<class T> concept SizedRange = /* see definition */; // views template<class T> inline constexpr bool enable_view = /* see definition */; struct view_base { }; template<class T> concept View = /* see definition */; // other range refinements template<class R, class T> concept OutputRange = /* see definition */; template<class T> concept InputRange = /* see definition */; template<class T> concept ForwardRange = /* see definition */; template<class T> concept BidirectionalRange = /* see definition */; template<class T> concept RandomAccessRange = /* see definition */; template<class T> concept ContiguousRange = /* see definition */; template<class T> concept CommonRange = /* see definition */; template<class T> concept ViewableRange = /* see definition */; // class template view_interface template<class D> requires is_class_v<D> && Same<D, remove_cv_t<D>> class view_interface; // sub-ranges enum class subrange_kind : bool { unsized, sized }; template<Iterator I, Sentinel<I> S = I, subrange_kind K = /* see definition */> requires (K == subrange_kind::sized || !SizedSentinel<S, I>) class subrange; // dangling iterator handling struct dangling; template<Range R> using safe_iterator_t = conditional_t<__ForwardingRange<R>, iterator_t<R>, dangling>; template<Range R> using safe_subrange_t = conditional_t<__ForwardingRange<R>, subrange<iterator_t<R>>, dangling>; // empty view template<class T> requires is_object_v<T> class empty_view; namespace view { template<class T> inline constexpr empty_view<T> empty{}; } // single view template<CopyConstructible T> requires is_object_v<T> class single_view; namespace view { inline constexpr /* unspecified */ single = /* unspecified */; } // iota view template<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t> requires __WeaklyEqualityComparableWith<W, Bound> class iota_view; namespace view { inline constexpr /* unspecified */ iota = /* unspecified */; } // all view namespace view { inline constexpr /* unspecified */ all = /* unspecified */; } template<ViewableRange R> using all_view = decltype(view::all(declval<R>())); template<Range R> requires is_object_v<R> class ref_view; // filter view template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred> requires View<V> && is_object_v<Pred> class filter_view; namespace view { inline constexpr /* unspecified */ filter = /* unspecified */; } // transform view template<InputRange V, CopyConstructible F> requires View<V> && is_object_v<F> && RegularInvocable<F&, iter_reference_t<iterator_t<V>>> class transform_view; namespace view { inline constexpr /* unspecified */ transform = /* unspecified */; } // take view template<View> class take_view; namespace view { inline constexpr /* unspecified */ take = /* unspecified */; } // join view template<InputRange V> requires View<V> && InputRange<iter_reference_t<iterator_t<V>>> && (is_reference_v<iter_reference_t<iterator_t<V>>> || View<iter_value_t<iterator_t<V>>>) class join_view; namespace view { inline constexpr /* unspecified */ join = /* unspecified */; } // split view template<class R> concept __TinyRange = /* see definition */; // exposition only template<InputRange V, ForwardRange Pattern> requires View<V> && View<Pattern> && IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (ForwardRange<V> || __TinyRange<Pattern>) class split_view; namespace view { inline constexpr /* unspecified */ split = /* unspecified */; } // counted view namespace view { inline constexpr /* unspecified */ counted = /* unspecified */; } // common view template<View V> requires (!CommonRange<V>) class common_view; namespace view { inline constexpr /* unspecified */ common = /* unspecified */; } // reverse view template<View V> requires BidirectionalRange<V> class reverse_view; namespace view { inline constexpr /* unspecified */ reverse = /* unspecified */; } } namespace std { namespace view = ranges::view; template<class I, class S, ranges::subrange_kind K> struct tuple_size<ranges::subrange<I, S, K>> : integral_constant<size_t, 2> {}; template<class I, class S, ranges::subrange_kind K> struct tuple_element<0, ranges::subrange<I, S, K>> { using type = I; }; template<class I, class S, ranges::subrange_kind K> struct tuple_element<1, ranges::subrange<I, S, K>> { using type = S; }; }
Concept Range
namespace std::ranges { template<class T> concept __RangeImpl = // exposition only requires(T&& t) { ranges::begin(std::forward<T>(t));// sometimes equality-preserving (see definition) ranges::end(std::forward<T>(t)); }; template<class T> concept Range = __RangeImpl<T&>; template<class T> concept __ForwardingRange = // exposition only Range<T> && __RangeImpl<T>; }
Concept SizedRange
namespace std::ranges { template<class T> concept SizedRange = Range<T> && !disable_sized_range<remove_cvref_t<T>> && requires(T& t) { ranges::size(t); }; }
Concept View
namespace std::ranges { template<class T> inline constexpr bool enable_view = /* see definition */; template<class T> concept View = Range<T> && Semiregular<T> && enable_view<T>; }
Concept OutputRange
namespace std::ranges { template<class R, class T> concept OutputRange = Range<R> && OutputIterator<iterator_t<R>, T>; }
Concept InputRange
namespace std::ranges { template<class T> concept InputRange = Range<T> && InputIterator<iterator_t<T>>; }
Concept ForwardRange
namespace std::ranges { template<class T> concept ForwardRange = InputRange<T> && ForwardIterator<iterator_t<T>>; }
Concept BidirectionalRange
namespace std::ranges { template<class T> concept BidirectionalRange = ForwardRange<T> && BidirectionalIterator<iterator_t<T>>; }
Concept RandomAccessRange
namespace std::ranges { template<class T> concept RandomAccessRange = BidirectionalRange<T> && RandomAccessIterator<iterator_t<T>>; }
Concept ContiguousRange
namespace std::ranges { template<class T> concept ContiguousRange = RandomAccessRange<T> && ContiguousIterator<iterator_t<T>> && requires(T& t) { { ranges::data(t) } -> Same<add_pointer_t<iter_reference_t<iterator_t<T>>>>; }; }
Concept CommonRange
Concept ViewableRange
Helper concepts
namespace std::ranges { // unspecified, for name lookup only template<class R> concept __SimpleView = // exposition only View<R> && Range<const R> && Same<iterator_t<R>, iterator_t<const R>> && Same<sentinel_t<R>, sentinel_t<const R>>; template<InputIterator I> concept __HasArrow = // exposition only is_pointer_v<I> || requires(I i) { i.operator->(); }; template<class T, class U> concept __NotSameAs = // exposition only !Same<remove_cvref_t<T>, remove_cvref_t<U>>; template<class I> concept _Decrementable = // exposition only Incrementable<I> && requires(I i) { { --i } -> Same<I&>; { i-- } -> Same<I>; }; template<class I> concept _Advanceable = // exposition only _Decrementable<I> && StrictTotallyOrdered<I> && requires(I i, const I j, const iter_difference_t<I> n) { { i += n } -> Same<I&>; { i -= n } -> Same<I&>; { j + n } -> Same<I>; { n + j } -> Same<I>; { j - n } -> Same<I>; { j - j } -> Same<iter_difference_t<I>>; }; }
Note: These names are only for exposition, they are not part of the interface.
Class template std::ranges::view_interface
namespace std::ranges { template<class D> requires is_class_v<D> && Same<D, remove_cv_t<D>> class view_interface : public view_base { private: constexpr D& derived() noexcept { // exposition only return static_cast<D&>(*this); } constexpr const D& derived() const noexcept { // exposition only return static_cast<const D&>(*this); } public: constexpr bool empty() requires ForwardRange<D> { return ranges::begin(derived()) == ranges::end(derived()); } constexpr bool empty() const requires ForwardRange<const D> { return ranges::begin(derived()) == ranges::end(derived()); } constexpr explicit operator bool() requires requires { ranges::empty(derived()); } { return !ranges::empty(derived()); } constexpr explicit operator bool() const requires requires { ranges::empty(derived()); } { return !ranges::empty(derived()); } constexpr auto data() requires ContiguousIterator<iterator_t<D>> { return ranges::empty(derived()) ? nullptr : addressof(*ranges::begin(derived())); } constexpr auto data() const requires Range<const D> && ContiguousIterator<iterator_t<const D>> { return ranges::empty(derived()) ? nullptr : addressof(*ranges::begin(derived())); } constexpr auto size() requires ForwardRange<D> && SizedSentinel<sentinel_t<D>, iterator_t<D>> { return ranges::end(derived()) - ranges::begin(derived()); } constexpr auto size() const requires ForwardRange<const D> && SizedSentinel<sentinel_t<const D>, iterator_t<const D>> { return ranges::end(derived()) - ranges::begin(derived()); } constexpr decltype(auto) front() requires ForwardRange<D>; constexpr decltype(auto) front() const requires ForwardRange<const D>; constexpr decltype(auto) back() requires BidirectionalRange<D> && CommonRange<D>; constexpr decltype(auto) back() const requires BidirectionalRange<const D> && CommonRange<const D>; template<RandomAccessRange R = D> constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n) { return ranges::begin(derived())[n]; } template<RandomAccessRange R = const D> constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n) const { return ranges::begin(derived())[n]; } }; }
Class template std::ranges::subrange
namespace std::ranges { template<class T> concept __PairLike = // exposition only !is_reference_v<T> && requires(T t) { typename tuple_size<T>::type; // ensures tuple_size<T> is complete requires DerivedFrom<tuple_size<T>, integral_constant<size_t, 2>>; typename tuple_element_t<0, remove_const_t<T>>; typename tuple_element_t<1, remove_const_t<T>>; { get<0>(t) } -> const tuple_element_t<0, T>&; { get<1>(t) } -> const tuple_element_t<1, T>&; }; template<class T, class U, class V> concept __PairLikeConvertibleTo = // exposition only !Range<T> && __PairLike<remove_reference_t<T>> && requires(T&& t) { { get<0>(std::forward<T>(t)) } -> ConvertibleTo<U>; { get<1>(std::forward<T>(t)) } -> ConvertibleTo<V>; }; template<class T, class U, class V> concept __PairLikeConvertibleFrom = // exposition only !Range<T> && __PairLike<T> && Constructible<T, U, V>; template<class T> concept __IteratorSentinelPair = // exposition only !Range<T> && __PairLike<T> && Sentinel<tuple_element_t<1, T>, tuple_element_t<0, T>>; template<Iterator I, Sentinel<I> S = I, subrange_kind K = SizedSentinel<S, I> ? subrange_kind::sized : subrange_kind::unsized> requires (K == subrange_kind::sized || !SizedSentinel<S, I>) class subrange : public view_interface<subrange<I, S, K>> { private: static constexpr bool StoreSize = // exposition only K == subrange_kind::sized && !SizedSentinel<S, I>; I begin_ = I(); // exposition only S end_ = S(); // exposition only iter_difference_t<I> size_ = 0; // exposition only; present only // when StoreSize is true public: subrange() = default; constexpr subrange(I i, S s) requires (!StoreSize); constexpr subrange(I i, S s, iter_difference_t<I> n) requires (K == subrange_kind::sized); template<__NotSameAs<subrange> R> requires __ForwardingRange<R> && ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S> constexpr subrange(R&& r) requires (!StoreSize || SizedRange<R>); template<__ForwardingRange R> requires ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S> constexpr subrange(R&& r, iter_difference_t<I> n) requires (K == subrange_kind::sized) : subrange{ranges::begin(r), ranges::end(r), n} {} template<__NotSameAs<subrange> PairLike> requires __PairLikeConvertibleTo<PairLike, I, S> constexpr subrange(PairLike&& r) requires (!StoreSize) : subrange{std::get<0>(std::forward<PairLike>(r)), std::get<1>(std::forward<PairLike>(r))} {} template<__PairLikeConvertibleTo<I, S> PairLike> constexpr subrange(PairLike&& r, iter_difference_t<I> n) requires (K == subrange_kind::sized) : subrange{std::get<0>(std::forward<PairLike>(r)), std::get<1>(std::forward<PairLike>(r)), n} {} template<__NotSameAs<subrange> PairLike> requires __PairLikeConvertibleFrom<PairLike, const I&, const S&> constexpr operator PairLike() const; constexpr I begin() const; constexpr S end() const; constexpr bool empty() const; constexpr iter_difference_t<I> size() const requires (K == subrange_kind::sized); [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const; [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const requires BidirectionalIterator<I>; constexpr subrange& advance(iter_difference_t<I> n); friend constexpr I begin(subrange&& r) { return r.begin(); } friend constexpr S end(subrange&& r) { return r.end(); } }; template<Iterator I, Sentinel<I> S> subrange(I, S, iter_difference_t<I>) -> subrange<I, S, subrange_kind::sized>; template<__IteratorSentinelPair P> subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>; template<__IteratorSentinelPair P> subrange(P, iter_difference_t<tuple_element_t<0, P>>) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>; template<__ForwardingRange R> subrange(R&&) -> subrange<iterator_t<R>, sentinel_t<R>, (SizedRange<R> || SizedSentinel<sentinel_t<R>, iterator_t<R>>) ? subrange_kind::sized : subrange_kind::unsized>; template<__ForwardingRange R> subrange(R&&, iter_difference_t<iterator_t<R>>) -> subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>; template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(const subrange<I, S, K>& r); } namespace std { using ranges::get; }
Class std::ranges::dangling
namespace std::ranges { struct dangling { constexpr dangling() noexcept = default; template<class... Args> constexpr dangling(Args&&...) noexcept { } }; }
Class template std::ranges::empty_view
namespace std::ranges { template<class T> requires is_object_v<T> class empty_view : public view_interface<empty_view<T>> { public: static constexpr T* begin() noexcept { return nullptr; } static constexpr T* end() noexcept { return nullptr; } static constexpr T* data() noexcept { return nullptr; } static constexpr ptrdiff_t size() noexcept { return 0; } static constexpr bool empty() noexcept { return true; } friend constexpr T* begin(empty_view) noexcept { return nullptr; } friend constexpr T* end(empty_view) noexcept { return nullptr; } }; }
Class template std::ranges::empty_view
namespace std::ranges { template<CopyConstructible T> requires is_object_v<T> class single_view : public view_interface<single_view<T>> { private: semiregular<T> value_; // exposition only public: single_view() = default; constexpr explicit single_view(const T& t); constexpr explicit single_view(T&& t); template<class... Args> requires Constructible<T, Args...> constexpr single_view(in_place_t, Args&&... args); constexpr T* begin() noexcept; constexpr const T* begin() const noexcept; constexpr T* end() noexcept; constexpr const T* end() const noexcept; static constexpr ptrdiff_t size() noexcept; constexpr T* data() noexcept; constexpr const T* data() const noexcept; }; }
Class template std::ranges::iota_view
namespace std::ranges { template<class I> concept _Decrementable = // exposition only /* see definition */; template<class I> concept _Advanceable = // exposition only /* see definition */; template<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t> requires __WeaklyEqualityComparableWith<W, Bound> class iota_view : public view_interface<iota_view<W, Bound>> { private: // class iota_view::iterator struct iterator; // exposition only // class iota_view::sentinel struct sentinel; // exposition only W value_ = W(); // exposition only Bound bound_ = Bound(); // exposition only public: iota_view() = default; constexpr explicit iota_view(W value); constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound); constexpr iterator begin() const; constexpr sentinel end() const; constexpr iterator end() const requires Same<W, Bound>; constexpr auto size() const requires (Same<W, Bound> && _Advanceable<W>) || (Integral<W> && Integral<Bound>) || SizedSentinel<Bound, W> { return bound_ - value_; } }; template<class W, class Bound> requires (!Integral<W> || !Integral<Bound> || is_signed_v<W> == is_signed_v<Bound>) iota_view(W, Bound) -> iota_view<W, Bound>; }
Class std::ranges::iota_view::iterator
namespace std::ranges { template<class W, class Bound> struct iota_view<W, Bound>::iterator { private: W value_ = W(); // exposition only public: using iterator_category = /* see definition */; using value_type = W; using difference_type = iter_difference_t<W>; iterator() = default; constexpr explicit iterator(W value); constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>); constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires Incrementable<W>; constexpr iterator& operator--() requires _Decrementable<W>; constexpr iterator operator--(int) requires _Decrementable<W>; constexpr iterator& operator+=(difference_type n) requires _Advanceable<W>; constexpr iterator& operator-=(difference_type n) requires _Advanceable<W>; constexpr W operator[](difference_type n) const requires _Advanceable<W>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable<W>; friend constexpr bool operator!=(const iterator& x, const iterator& y) requires EqualityComparable<W>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>; friend constexpr iterator operator+(iterator i, difference_type n) requires _Advanceable<W>; friend constexpr iterator operator+(difference_type n, iterator i) requires _Advanceable<W>; friend constexpr iterator operator-(iterator i, difference_type n) requires _Advanceable<W>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires _Advanceable<W>; }; }
Class std::ranges::iota_view::sentinel
namespace std::ranges { template<class W, class Bound> struct iota_view<W, Bound>::sentinel { private: Bound bound_ = Bound(); // exposition only public: sentinel() = default; constexpr explicit sentinel(Bound bound); friend constexpr bool operator==(const iterator& x, const sentinel& y); friend constexpr bool operator==(const sentinel& x, const iterator& y); friend constexpr bool operator!=(const iterator& x, const sentinel& y); friend constexpr bool operator!=(const sentinel& x, const iterator& y); }; }
Class template std::ranges::ref_view
namespace std::ranges { template<Range R> requires is_object_v<R> class ref_view : public view_interface<ref_view<R>> { private: R* r_ = nullptr; // exposition only public: constexpr ref_view() noexcept = default; template<__NotSameAs<ref_view> T> requires /* see definition */ constexpr ref_view(T&& t); constexpr R& base() const { return *r_; } constexpr iterator_t<R> begin() const { return ranges::begin(*r_); } constexpr sentinel_t<R> end() const { return ranges::end(*r_); } constexpr bool empty() const requires requires { ranges::empty(*r_); } { return ranges::empty(*r_); } constexpr auto size() const requires SizedRange<R> { return ranges::size(*r_); } constexpr auto data() const requires ContiguousRange<R> { return ranges::data(*r_); } friend constexpr iterator_t<R> begin(ref_view r) { return r.begin(); } friend constexpr sentinel_t<R> end(ref_view r) { return r.end(); } }; template<class R> ref_view(R&) -> ref_view<R>; }
Class template std::ranges::filter_view
namespace std::ranges { template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred> requires View<V> && is_object_v<Pred> class filter_view : public view_interface<filter_view<V, Pred>> { private: V base_ = V(); // exposition only semiregular<Pred> pred_; // exposition only // class filter_view::iterator class iterator; // exposition only // class filter_view::sentinel class sentinel; // exposition only public: filter_view() = default; constexpr filter_view(V base, Pred pred); template<InputRange R> requires ViewableRange<R> && Constructible<V, all_view<R>> constexpr filter_view(R&& r, Pred pred); constexpr V base() const; constexpr iterator begin(); constexpr auto end() { if constexpr (CommonRange<V>) return iterator{*this, ranges::end(base_)}; else return sentinel{*this}; } }; template<class R, class Pred> filter_view(R&&, Pred) -> filter_view<all_view<R>, Pred>; }
Class std::ranges::filter_view::iterator
namespace std::ranges { template<class V, class Pred> class filter_view<V, Pred>::iterator { private: iterator_t<V> current_ = iterator_t<V>(); // exposition only filter_view* parent_ = nullptr; // exposition only public: using iterator_concept = /* see definition */; using iterator_category = /* see definition */; using value_type = iter_value_t<iterator_t<V>>; using difference_type = iter_difference_t<iterator_t<V>>; iterator() = default; constexpr iterator(filter_view& parent, iterator_t<V> current); constexpr iterator_t<V> base() const; constexpr iter_reference_t<iterator_t<V>> operator*() const; constexpr iterator_t<V> operator->() const requires has-arrow<iterator_t<V>>; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires ForwardRange<V>; constexpr iterator& operator--() requires BidirectionalRange<V>; constexpr iterator operator--(int) requires BidirectionalRange<V>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<V>>; friend constexpr bool operator!=(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<V>>; friend constexpr iter_rvalue_reference_t<iterator_t<V>> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires IndirectlySwappable<iterator_t<V>>; }; }
Class std::ranges::filter_view::sentinel
namespace std::ranges { template<class V, class Pred> class filter_view<V, Pred>::sentinel { private: sentinel_t<V> end_ = sentinel_t<V>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(filter_view& parent); constexpr sentinel_t<V> base() const; friend constexpr bool operator==(const iterator& x, const sentinel& y); friend constexpr bool operator==(const sentinel& x, const iterator& y); friend constexpr bool operator!=(const iterator& x, const sentinel& y); friend constexpr bool operator!=(const sentinel& x, const iterator& y); }; }
Class template std::ranges::transform_view
namespace std::ranges { template<InputRange V, CopyConstructible F> requires View<V> && is_object_v<F> && RegularInvocable<F&, iter_reference_t<iterator_t<V>>> class transform_view : public view_interface<transform_view<V, F>> { private: // class template transform_view::iterator template<bool> struct iterator; // exposition only // class template transform_view::sentinel template<bool> struct sentinel; // exposition only V base_ = V(); // exposition only semiregular<F> fun_; // exposition only public: transform_view() = default; constexpr transform_view(V base, F fun); template<InputRange R> requires ViewableRange<R> && Constructible<V, all_view<R>> constexpr transform_view(R&& r, F fun); constexpr V base() const; constexpr iterator<false> begin(); constexpr iterator<true> begin() const requires Range<const V> && RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>; constexpr sentinel<false> end(); constexpr iterator<false> end() requires CommonRange<V>; constexpr sentinel<true> end() const requires Range<const V> && RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>; constexpr iterator<true> end() const requires CommonRange<const V> && RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>; constexpr auto size() requires SizedRange<V> { return ranges::size(base_); } constexpr auto size() const requires SizedRange<const V> { return ranges::size(base_); } }; template<class R, class F> transform_view(R&&, F) -> transform_view<all_view<R>, F>; }
Class template std::ranges::transform_view::iterator
namespace std::ranges { template<class V, class F> template<bool Const> class transform_view<V, F>::iterator { private: using Parent = // exposition only conditional_t<Const, const transform_view, transform_view>; using Base = // exposition only conditional_t<Const, const V, V>; iterator_t<Base> current_ = // exposition only iterator_t<Base>(); Parent* parent_ = nullptr; // exposition only public: using iterator_concept = /* see definition */; using iterator_category = /* see definition */; using value_type = remove_cvref_t<invoke_result_t<F&, iter_reference_t<iterator_t<Base>>>>; using difference_type = iter_difference_t<iterator_t<Base>>; iterator() = default; constexpr iterator(Parent& parent, iterator_t<Base> current); constexpr iterator(iterator<!Const> i) requires Const && ConvertibleTo<iterator_t<V>, iterator_t<Base>>; constexpr iterator_t<Base> base() const; constexpr decltype(auto) operator*() const { return invoke(*parent_->fun_, *current_); } constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires ForwardRange<Base>; constexpr iterator& operator--() requires BidirectionalRange<Base>; constexpr iterator operator--(int) requires BidirectionalRange<Base>; constexpr iterator& operator+=(difference_type n) requires RandomAccessRange<Base>; constexpr iterator& operator-=(difference_type n) requires RandomAccessRange<Base>; constexpr decltype(auto) operator[](difference_type n) const requires RandomAccessRange<Base> { return invoke(*parent_->fun_, current_[n]); } friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<Base>>; friend constexpr bool operator!=(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<Base>>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires RandomAccessRange<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires RandomAccessRange<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires RandomAccessRange<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires RandomAccessRange<Base>; friend constexpr iterator operator+(iterator i, difference_type n) requires RandomAccessRange<Base>; friend constexpr iterator operator+(difference_type n, iterator i) requires RandomAccessRange<Base>; friend constexpr iterator operator-(iterator i, difference_type n) requires RandomAccessRange<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires RandomAccessRange<Base>; friend constexpr decltype(auto) iter_move(const iterator& i) noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_))) { if constexpr (is_lvalue_reference_v<decltype(*i)>) return std::move(*i); else return *i; } friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires IndirectlySwappable<iterator_t<Base>>; }; }
Class template std::ranges::transform_view::sentinel
namespace std::ranges { template<class V, class F> template<bool Const> class transform_view<V, F>::sentinel { private: using Parent = // exposition only conditional_t<Const, const transform_view, transform_view>; using Base = conditional_t<Const, const V, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end); constexpr sentinel(sentinel<!Const> i) requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y); friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y); friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y); friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y); friend constexpr iter_difference_t<iterator_t<Base>> operator-(const iterator<Const>& x, const sentinel& y) requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>; friend constexpr iter_difference_t<iterator_t<Base>> operator-(const sentinel& y, const iterator<Const>& x) requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>; }; }
Class template std::ranges::take_view
namespace std::ranges { template<View V> class take_view : public view_interface<take_view<V>> { private: V base_ = V(); // exposition only iter_difference_t<iterator_t<V>> count_ = 0; // exposition only // class template take_view::sentinel template<bool> struct sentinel; // exposition only public: take_view() = default; constexpr take_view(V base, iter_difference_t<iterator_t<V>> count); template<ViewableRange R> requires Constructible<V, all_view<R>> constexpr take_view(R&& r, iter_difference_t<iterator_t<V>> count); constexpr V base() const; constexpr auto begin() requires (!__SimpleView<V>) { if constexpr (SizedRange<V>) { if constexpr (RandomAccessRange<V>) return ranges::begin(base_); else return counted_iterator{ranges::begin(base_), size()}; } else return counted_iterator{ranges::begin(base_), count_}; } constexpr auto begin() const requires Range<const V> { if constexpr (SizedRange<const V>) { if constexpr (RandomAccessRange<const V>) return ranges::begin(base_); else return counted_iterator{ranges::begin(base_), size()}; } else return counted_iterator{ranges::begin(base_), count_}; } constexpr auto end() requires (!__SimpleView<V>) { if constexpr (SizedRange<V>) { if constexpr (RandomAccessRange<V>) return ranges::begin(base_) + size(); else return default_sentinel; } else return sentinel<false>{ranges::end(base_)}; } constexpr auto end() const requires Range<const V> { if constexpr (SizedRange<const V>) { if constexpr (RandomAccessRange<const V>) return ranges::begin(base_) + size(); else return default_sentinel; } else return sentinel<true>{ranges::end(base_)}; } constexpr auto size() requires SizedRange<V> { auto n = ranges::size(base_); return ranges::min(n, static_cast<decltype(n)>(count_)); } constexpr auto size() const requires SizedRange<const V> { auto n = ranges::size(base_); return ranges::min(n, static_cast<decltype(n)>(count_)); } }; template<Range R> take_view(R&&, iter_difference_t<iterator_t<R>>) -> take_view<all_view<R>>; }
Class template std::ranges::take_view::sentinel
namespace std::ranges { template<class V> template<bool Const> class take_view<V>::sentinel { private: using Base = conditional_t<Const, const V, V>; // exposition only using CI = counted_iterator<iterator_t<Base>>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end); constexpr sentinel(sentinel<!Const> s) requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; friend constexpr bool operator==(const sentinel& x, const CI& y); friend constexpr bool operator==(const CI& y, const sentinel& x); friend constexpr bool operator!=(const sentinel& x, const CI& y); friend constexpr bool operator!=(const CI& y, const sentinel& x); }; }
Class template std::ranges::join_view
namespace std::ranges { template<InputRange V> requires View<V> && InputRange<iter_reference_t<iterator_t<V>>> && (is_reference_v<iter_reference_t<iterator_t<V>>> || View<iter_value_t<iterator_t<V>>>) class join_view : public view_interface<join_view<V>> { private: using InnerRng = // exposition only iter_reference_t<iterator_t<V>>; // class template join_view::iterator template<bool Const> struct iterator; // exposition only // class template join_view::sentinel template<bool Const> struct sentinel; // exposition only V base_ = V(); // exposition only all_view<InnerRng> inner_ = // exposition only, present only when all_view<InnerRng>(); // !is_reference_v<InnerRng> public: join_view() = default; constexpr explicit join_view(V base); template<InputRange R> requires ViewableRange<R> && Constructible<V, all_view<R>> constexpr explicit join_view(R&& r); constexpr auto begin() { return iterator<__SimpleView<V>>{*this, ranges::begin(base_)}; } constexpr auto begin() const requires InputRange<const V> && is_reference_v<iter_reference_t<iterator_t<const V>>> { return iterator<true>{*this, ranges::begin(base_)}; } constexpr auto end() { if constexpr (ForwardRange<V> && is_reference_v<InnerRng> && ForwardRange<InnerRng> && CommonRange<V> && CommonRange<InnerRng>) return iterator<__SimpleView<V>>{*this, ranges::end(base_)}; else return sentinel<__SimpleView<V>>{*this}; } constexpr auto end() const requires InputRange<const V> && is_reference_v<iter_reference_t<iterator_t<const V>>> { if constexpr (ForwardRange<const V> && is_reference_v<iter_reference_t<iterator_t<const V>>> && ForwardRange<iter_reference_t<iterator_t<const V>>> && CommonRange<const V> && CommonRange<iter_reference_t<iterator_t<const V>>>) return iterator<true>{*this, ranges::end(base_)}; else return sentinel<true>{*this}; } }; template<class R> explicit join_view(R&&) -> join_view<all_view<R>>; }
Class template std::ranges::join_view::iterator
namespace std::ranges { template<class V> template<bool Const> struct join_view<V>::iterator { private: using Parent = // exposition only conditional_t<Const, const join_view, join_view>; using Base = conditional_t<Const, const V, V>; // exposition only static constexpr bool ref_is_glvalue = // exposition only is_reference_v<iter_reference_t<iterator_t<Base>>>; iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only iterator_t<iter_reference_t<iterator_t<Base>>> inner_ = // exposition only iterator_t<iter_reference_t<iterator_t<Base>>>(); Parent* parent_ = nullptr; // exposition only constexpr void satisfy(); // exposition only public: using iterator_concept = /* see definition */; using iterator_category = /* see definition */; using value_type = iter_value_t<iterator_t<iter_reference_t<iterator_t<Base>>>>; using difference_type = /* see definition */; iterator() = default; constexpr iterator(Parent& parent, iterator_t<V> outer); constexpr iterator(iterator<!Const> i) requires Const && ConvertibleTo<iterator_t<V>, iterator_t<Base>> && ConvertibleTo<iterator_t<InnerRng>, iterator_t<iter_reference_t<iterator_t<Base>>>>; constexpr decltype(auto) operator*() const { return *inner_; } constexpr iterator_t<Base> operator->() const requires __HasArrow<iterator_t<Base>>; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires ref_is_glvalue && ForwardRange<Base> && ForwardRange<iter_reference_t<iterator_t<Base>>>; constexpr iterator& operator--() requires ref_is_glvalue && BidirectionalRange<Base> && BidirectionalRange<iter_reference_t<iterator_t<Base>>>; constexpr iterator operator--(int) requires ref_is_glvalue && BidirectionalRange<Base> && BidirectionalRange<iter_reference_t<iterator_t<Base>>>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> && EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>; friend constexpr bool operator!=(const iterator& x, const iterator& y) requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> && EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>; friend constexpr decltype(auto) iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.inner_))) { return ranges::iter_move(i.inner_); } friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_))); }; }
Class template std::ranges::join_view::sentinel
namespace std::ranges { template<class V> template<bool Const> struct join_view<V>::sentinel { private: using Parent = // exposition only conditional_t<Const, const join_view, join_view>; using Base = conditional_t<Const, const V, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(Parent& parent); constexpr sentinel(sentinel<!Const> s) requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>; friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y); friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y); friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y); friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y); }; }
Class template std::ranges::split_view
namespace std::ranges { template<auto> struct __require_constant; // exposition only template<class R> concept __TinyRange = // exposition only SizedRange<R> && requires { typename __require_constant<remove_reference_t<R>::size()>; } && (remove_reference_t<R>::size() <= 1); template<InputRange V, ForwardRange Pattern> requires View<V> && View<Pattern> && IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (ForwardRange<V> || __TinyRange<Pattern>) class split_view : public view_interface<split_view<V, Pattern>> { private: V base_ = V(); // exposition only Pattern pattern_ = Pattern(); // exposition only iterator_t<V> current_ = iterator_t<V>(); // exposition only, present only if // !ForwardRange<V> // class template split_view::outer_iterator template<bool> struct outer_iterator; // exposition only // class template split_view::inner_iterator template<bool> struct inner_iterator; // exposition only public: split_view() = default; constexpr split_view(V base, Pattern pattern); template<InputRange R, ForwardRange P> requires Constructible<V, all_view<R>> && Constructible<Pattern, all_view<P>> constexpr split_view(R&& r, P&& p); template<InputRange R> requires Constructible<V, all_view<R>> && Constructible<Pattern, single_view<iter_value_t<iterator_t<R>>>> constexpr split_view(R&& r, iter_value_t<iterator_t<R>> e); constexpr auto begin() { if constexpr (ForwardRange<V>) return outer_iterator<__SimpleView<V>>{*this, ranges::begin(base_)}; else { current_ = ranges::begin(base_); return outer_iterator<false>{*this}; } } constexpr auto begin() const requires ForwardRange<V> && ForwardRange<const V> { return outer_iterator<true>{*this, ranges::begin(base_)}; } constexpr auto end() requires ForwardRange<V> && CommonRange<V> { return outer_iterator<__SimpleView<V>>{*this, ranges::end(base_)}; } constexpr auto end() const { if constexpr (ForwardRange<V> && ForwardRange<const V> && CommonRange<const V>) return outer_iterator<true>{*this, ranges::end(base_)}; else return default_sentinel; } }; template<class R, class P> split_view(R&&, P&&) -> split_view<all_view<R>, all_view<P>>; template<InputRange R> split_view(R&&, iter_value_t<iterator_t<R>>) -> split_view<all_view<R>, single_view<iter_value_t<iterator_t<R>>>>; }
Class template std::ranges::split_view::outer_iterator
namespace std::ranges { template<class V, class Pattern> template<bool Const> struct split_view<V, Pattern>::outer_iterator { private: using Parent = // exposition only conditional_t<Const, const split_view, split_view>; using Base = // exposition only conditional_t<Const, const V, V>; Parent* parent_ = nullptr; // exposition only iterator_t<Base> current_ = // exposition only, present only iterator_t<Base>(); // if V models ForwardRange public: using iterator_concept = conditional_t<ForwardRange<Base>, forward_iterator_tag, input_iterator_tag>; using iterator_category = input_iterator_tag; struct value_type; using difference_type = iter_difference_t<iterator_t<Base>>; outer_iterator() = default; constexpr explicit outer_iterator(Parent& parent) requires (!ForwardRange<Base>); constexpr outer_iterator(Parent& parent, iterator_t<Base> current) requires ForwardRange<Base>; constexpr outer_iterator(outer_iterator<!Const> i) requires Const && ConvertibleTo<iterator_t<V>, iterator_t<const V>>; constexpr value_type operator*() const; constexpr outer_iterator& operator++(); constexpr decltype(auto) operator++(int) { if constexpr (ForwardRange<Base>) { auto tmp = *this; ++*this; return tmp; } else ++*this; } friend constexpr bool operator==(const outer_iterator& x, const outer_iterator& y) requires ForwardRange<Base>; friend constexpr bool operator!=(const outer_iterator& x, const outer_iterator& y) requires ForwardRange<Base>; friend constexpr bool operator==(const outer_iterator& x, default_sentinel_t); friend constexpr bool operator==(default_sentinel_t, const outer_iterator& x); friend constexpr bool operator!=(const outer_iterator& x, default_sentinel_t y); friend constexpr bool operator!=(default_sentinel_t y, const outer_iterator& x); }; }
Class std::ranges::split_view::outer_iterator::value_type
namespace std::ranges { template<class V, class Pattern> template<bool Const> struct split_view<V, Pattern>::outer_iterator<Const>::value_type { private: outer_iterator i_ = outer_iterator(); // exposition only public: value_type() = default; constexpr explicit value_type(outer_iterator i); constexpr inner_iterator<Const> begin() const; constexpr default_sentinel_t end() const; }; }
Class template std::ranges::split_view::inner_iterator
namespace std::ranges { template<class V, class Pattern> template<bool Const> struct split_view<V, Pattern>::inner_iterator { private: using Base = conditional_t<Const, const V, V>; // exposition only outer_iterator<Const> i_ = outer_iterator<Const>(); // exposition only bool incremented_ = false; // exposition only public: using iterator_concept = typename outer_iterator<Const>::iterator_concept; using iterator_category = /* see definition */; using value_type = iter_value_t<iterator_t<Base>>; using difference_type = iter_difference_t<iterator_t<Base>>; inner_iterator() = default; constexpr explicit inner_iterator(outer_iterator<Const> i); constexpr decltype(auto) operator*() const { return *i_.current; } constexpr inner_iterator& operator++(); constexpr decltype(auto) operator++(int) { if constexpr (ForwardRange<V>) { auto tmp = *this; ++*this; return tmp; } else ++*this; } friend constexpr bool operator==(const inner_iterator& x, const inner_iterator& y) requires ForwardRange<Base>; friend constexpr bool operator!=(const inner_iterator& x, const inner_iterator& y) requires ForwardRange<Base>; friend constexpr bool operator==(const inner_iterator& x, default_sentinel_t); friend constexpr bool operator==(default_sentinel_t, const inner_iterator& x); friend constexpr bool operator!=(const inner_iterator& x, default_sentinel_t y); friend constexpr bool operator!=(default_sentinel_t y, const inner_iterator& x); friend constexpr decltype(auto) iter_move(const inner_iterator& i) noexcept(noexcept(ranges::iter_move(i.i_.current))) { return ranges::iter_move(i.i_.current); } friend constexpr void iter_swap(const inner_iterator& x, const inner_iterator& y) noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current))) requires IndirectlySwappable<iterator_t<Base>>; }; }
Class template std::ranges::common_view
namespace std::ranges { template<View V> requires (!CommonRange<V>) class common_view : public view_interface<common_view<V>> { private: V base_ = V(); // exposition only public: common_view() = default; constexpr explicit common_view(V r); template<ViewableRange R> requires (!CommonRange<R> && Constructible<V, all_view<R>>) constexpr explicit common_view(R&& r); constexpr V base() const; constexpr auto size() requires SizedRange<V> { return ranges::size(base_); } constexpr auto size() const requires SizedRange<const V> { return ranges::size(base_); } constexpr auto begin() { if constexpr (RandomAccessRange<V> && SizedRange<V>) return ranges::begin(base_); else return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_)); } constexpr auto begin() const requires Range<const V> { if constexpr (RandomAccessRange<const V> && SizedRange<const V>) return ranges::begin(base_); else return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_)); } constexpr auto end() { if constexpr (RandomAccessRange<V> && SizedRange<V>) return ranges::begin(base_) + ranges::size(base_); else return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_)); } constexpr auto end() const requires Range<const V> { if constexpr (RandomAccessRange<const V> && SizedRange<const V>) return ranges::begin(base_) + ranges::size(base_); else return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_)); } }; template<class R> common_view(R&&) -> common_view<all_view<R>>; }
Class template std::ranges::reverse_view
namespace std::ranges { template<View V> requires BidirectionalRange<V> class reverse_view : public view_interface<reverse_view<V>> { private: V base_ = V(); // exposition only public: reverse_view() = default; constexpr explicit reverse_view(V r); template<ViewableRange R> requires BidirectionalRange<R> && Constructible<V, all_view<R>> constexpr explicit reverse_view(R&& r); constexpr V base() const; constexpr reverse_iterator<iterator_t<V>> begin(); constexpr reverse_iterator<iterator_t<V>> begin() requires CommonRange<V>; constexpr reverse_iterator<iterator_t<const V>> begin() const requires CommonRange<const V>; constexpr reverse_iterator<iterator_t<V>> end(); constexpr reverse_iterator<iterator_t<const V>> end() const requires CommonRange<const V>; constexpr auto size() requires SizedRange<V> { return ranges::size(base_); } constexpr auto size() const requires SizedRange<const V> { return ranges::size(base_); } }; template<class R> reverse_view(R&&) -> reverse_view<all_view<R>>; }