16 KiB
[range.subrange]
25 Ranges library [ranges]
25.5 Range utilities [range.utility]
25.5.4 Sub-ranges [range.subrange]
25.5.4.1 General [range.subrange.general]
The subrange class template combines together an iterator and a sentinel into a single object that models theview concept.
Additionally, it models thesized_range concept when the final template parameter issubrange_kind::sized.
namespace std::ranges {template<class From, class To>concept uses-nonqualification-pointer-conversion = // exposition only is_pointer_v && is_pointer_v &&<remove_pointer_t()[], remove_pointer_t()[]>; template<class From, class To>concept convertible-to-non-slicing = // exposition onlyconvertible_to<From, To> &&
<decay_t, decay_t>; template<class T, class U, class V>concept pair-like-convertible-from = // exposition only
&& !is_reference_v && pair-like &&constructible_from<T, U, V> &&convertible-to-non-slicing<U, tuple_element_t<0, T>> &&convertible_to<V, tuple_element_t<1, T>>; template<input_or_output_iterator I, sentinel_for S = I, subrange_kind K =sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>requires (K == subrange_kind::sized ||
<S, I>)class subrange : public view_interface<subrange<I, S, K>> {private:static constexpr bool StoreSize = // exposition only K == subrange_kind::sized &&
<S, I>;
I begin_ = I(); // exposition only S end_ = S(); // exposition only**make-unsigned-like-t<iter_difference_t> size_ = 0; // exposition only; present only// if StoreSize is truepublic: subrange() requires default_initializable = default; constexpr subrange(convertible-to-non-slicing auto i, S s) requires (!StoreSize); constexpr subrange(convertible-to-non-slicing auto i, S s, make-unsigned-like-t<iter_difference_t> n)requires (K == subrange_kind::sized); template<different-from R>requires borrowed_range &&convertible-to-non-slicing<iterator_t, I> &&convertible_to<sentinel_t, S>constexpr subrange(R&& r) requires (!StoreSize || sized_range); template<borrowed_range R>requires convertible-to-non-slicing<iterator_t, I> &&convertible_to<sentinel_t, S>constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t> n)requires (K == subrange_kind::sized): subrange{ranges::begin(r), ranges::end(r), n} {}template<different-from PairLike>requires pair-like-convertible-from<PairLike, const I&, const S&>constexpr operator PairLike() const; constexpr I begin() const requires copyable; constexpr I begin() requires (
); constexpr S end() const; constexpr bool empty() const; constexpr make-unsigned-like-t<iter_difference_t> size() constrequires (K == subrange_kind::sized); constexpr subrange next(iter_difference_t n = 1) const &requires forward_iterator; constexpr subrange next(iter_difference_t n = 1) &&; constexpr subrange prev(iter_difference_t n = 1) constrequires bidirectional_iterator; constexpr subrange& advance(iter_difference_t n); }; template<input_or_output_iterator I, sentinel_for S> subrange(I, S) -> subrange<I, S>; template<input_or_output_iterator I, sentinel_for S> subrange(I, S, make-unsigned-like-t<iter_difference_t>) -> subrange<I, S, subrange_kind::sized>; template<borrowed_range R> subrange(R&&) -> subrange<iterator_t, sentinel_t, (sized_range || sized_sentinel_for<sentinel_t, iterator_t>)? subrange_kind::sized : subrange_kind::unsized>; template<borrowed_range R> subrange(R&&, make-unsigned-like-t<range_difference_t>) -> subrange<iterator_t, sentinel_t, subrange_kind::sized>;}
25.5.4.2 Constructors and conversions [range.subrange.ctor]
constexpr subrange([convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<I> auto i, S s) requires (!StoreSize);
Preconditions: [i, s) is a valid range.
Effects: Initializes begin_ with std::move(i) and end_ withs.
constexpr subrange([convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<I> auto i, S s, make-unsigned-like-t<iter_difference_t<I>> n) requires (K == subrange_kind::sized);
Preconditions: [i, s) is a valid range, andn == to-unsigned-like(ranges::distance(i, s)) is true.
Effects: Initializes begin_ with std::move(i) and end_ withs.
If StoreSize is true, initializes size_ withn.
[Note 1:
Accepting the length of the range and storing it to later return fromsize() enables subrange to model sized_range even when it stores an iterator and sentinel that do not modelsized_sentinel_for.
â end note]
template<[different-from](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]")<subrange> R> requires [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]")<R> && [convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<iterator_t<R>, I> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<R>, S> constexpr subrange(R&& r) requires (!StoreSize || [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>);
Effects: Equivalent to:
-
If StoreSize is true,subrange(r, static_cast<decltype(size_)>(ranges::size(r))).
-
Otherwise, subrange(ranges::begin(r), ranges::end(r)).
template<[different-from](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]")<subrange> PairLike> requires [pair-like-convertible-from](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]")<PairLike, const I&, const S&> constexpr operator PairLike() const;
Effects: Equivalent to: return PairLike(begin_, end_);
25.5.4.3 Accessors [range.subrange.access]
constexpr I begin() const requires [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<I>;
Effects: Equivalent to: return begin_;
constexpr I begin() requires (<I>);
Effects: Equivalent to: return std::move(begin_);
constexpr S end() const;
Effects: Equivalent to: return end_;
constexpr bool empty() const;
Effects: Equivalent to: return begin_ == end_;
constexpr make-unsigned-like-t<iter_difference_t<I>> size() const requires (K == subrange_kind::sized);
Effects:
If StoreSize is true, equivalent to: return size_;
Otherwise, equivalent to: return to-unsigned-like(end_ - begin_);
constexpr subrange next(iter_difference_t<I> n = 1) const & requires [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<I>;
Effects: Equivalent to:auto tmp = *this; tmp.advance(n);return tmp;
constexpr subrange next(iter_difference_t<I> n = 1) &&;
Effects: Equivalent to:advance(n);return std::move(*this);
constexpr subrange prev(iter_difference_t<I> n = 1) const requires [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_iterator [iterator.concept.bidir]")<I>;
Effects: Equivalent to:auto tmp = *this; tmp.advance(-n);return tmp;
constexpr subrange& advance(iter_difference_t<I> n);
Effects: Equivalent to:if constexpr (bidirectional_iterator) {if (n < 0) { ranges::advance(begin_, n); if constexpr (StoreSize)size_ += to-unsigned-like(-n); return *this; }}auto d = n - ranges::advance(begin_, n, end_);if constexpr (StoreSize)size_ -= to-unsigned-like(d);return *this;
template<size_t N, class I, class S, subrange_kind K> requires ((N == 0 && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<I>) || N == 1) constexpr auto get(const subrange<I, S, K>& r); template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(subrange<I, S, K>&& r);
Effects: Equivalent to:if constexpr (N == 0)return r.begin();elsereturn r.end();