The
subrange class template combines together an
iterator and a sentinel into a single object that models the
view concept
. Additionally, it models the
sized_range concept when the final template parameter is
subrange_kind::sized.
namespace std::ranges {
template<class From, class To>
concept convertible-to-non-slicing =
convertible_to<From, To> &&
!(is_pointer_v<decay_t<From>> &&
is_pointer_v<decay_t<To>> &&
not-same-as<remove_pointer_t<decay_t<From>>, remove_pointer_t<decay_t<To>>>);
template<class T>
concept pair-like =
!is_reference_v<T> && requires(T t) {
typename tuple_size<T>::type;
requires derived_from<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) } -> convertible_to<const tuple_element_t<0, T>&>;
{ get<1>(t) } -> convertible_to<const tuple_element_t<1, T>&>;
};
template<class T, class U, class V>
concept pair-like-convertible-from =
!range<T> && pair-like<T> &&
constructible_from<T, U, V> &&
convertible-to-non-slicing<U, tuple_element_t<0, T>> &&
convertible_to<V, tuple_element_t<1, T>>;
template<class T>
concept iterator-sentinel-pair =
!range<T> && pair-like<T> &&
sentinel_for<tuple_element_t<1, T>, tuple_element_t<0, T>>;
template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
class subrange : public view_interface<subrange<I, S, K>> {
private:
static constexpr bool StoreSize =
K == subrange_kind::sized && !sized_sentinel_for<S, I>;
I begin_ = I();
S end_ = S();
make-unsigned-like-t<iter_difference_t<I>> size_ = 0;
public:
subrange() = default;
constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
make-unsigned-like-t<iter_difference_t<I>> n)
requires (K == subrange_kind::sized);
template<not-same-as<subrange> R>
requires borrowed_range<R> &&
convertible-to-non-slicing<iterator_t<R>, I> &&
convertible_to<sentinel_t<R>, S>
constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
template<borrowed_range R>
requires convertible-to-non-slicing<iterator_t<R>, I> &&
convertible_to<sentinel_t<R>, S>
constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
requires (K == subrange_kind::sized)
: subrange{ranges::begin(r), ranges::end(r), n}
{}
template<not-same-as<subrange> PairLike>
requires pair-like-convertible-from<PairLike, const I&, const S&>
constexpr operator PairLike() const;
constexpr I begin() const requires copyable<I>;
[[nodiscard]] constexpr I begin() requires (!copyable<I>);
constexpr S end() const;
constexpr bool empty() const;
constexpr make-unsigned-like-t<iter_difference_t<I>> size() const
requires (K == subrange_kind::sized);
[[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const &
requires forward_iterator<I>;
[[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;
[[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
requires bidirectional_iterator<I>;
constexpr subrange& advance(iter_difference_t<I> n);
};
template<input_or_output_iterator I, sentinel_for<I> S>
subrange(I, S) -> subrange<I, S>;
template<input_or_output_iterator I, sentinel_for<I> S>
subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) ->
subrange<I, S, subrange_kind::sized>;
template<iterator-sentinel-pair P>
subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
template<iterator-sentinel-pair P>
subrange(P, make-unsigned-like-t<iter_difference_t<tuple_element_t<0, P>>>) ->
subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
template<borrowed_range R>
subrange(R&&) ->
subrange<iterator_t<R>, sentinel_t<R>,
(sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
? subrange_kind::sized : subrange_kind::unsized>;
template<borrowed_range R>
subrange(R&&, make-unsigned-like-t<range_difference_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);
template<size_t N, class I, class S, subrange_kind K>
requires (N < 2)
constexpr auto get(subrange<I, S, K>&& r);
}
namespace std {
using ranges::get;
}