The
subrange class template combines together an
iterator and a sentinel into a single object that models the
View concept
. Additionally, it models the
SizedRange concept when the final template parameter is
subrange_kind::sized.
namespace std::ranges {
template<class T>
concept pair-like =
!is_reference_v<T> && requires(T t) {
typename tuple_size<T>::type;
requires DerivedFrom<tuple_size<T>, integral_constant<size_t, 2>>;
typename tuple_element_t<0, remove_const_t<T>>;
typename tuple_element_t<1, remove_const_t<T>>;
{ get<0>(t) } -> const tuple_element_t<0, T>&;
{ get<1>(t) } -> const tuple_element_t<1, T>&;
};
template<class T, class U, class V>
concept pair-like-convertible-to =
!Range<T> && pair-like<remove_reference_t<T>> &&
requires(T&& t) {
{ get<0>(std::forward<T>(t)) } -> ConvertibleTo<U>;
{ get<1>(std::forward<T>(t)) } -> ConvertibleTo<V>;
};
template<class T, class U, class V>
concept pair-like-convertible-from =
!Range<T> && pair-like<T> && Constructible<T, U, V>;
template<class T>
concept iterator-sentinel-pair =
!Range<T> && pair-like<T> &&
Sentinel<tuple_element_t<1, T>, tuple_element_t<0, T>>;
template<Iterator I, Sentinel<I> S = I, subrange_kind K =
SizedSentinel<S, I> ? subrange_kind::sized : subrange_kind::unsized>
requires (K == subrange_kind::sized || !SizedSentinel<S, I>)
class subrange : public view_interface<subrange<I, S, K>> {
private:
static constexpr bool StoreSize =
K == subrange_kind::sized && !SizedSentinel<S, I>;
I begin_ = I();
S end_ = S();
iter_difference_t<I> size_ = 0;
public:
subrange() = default;
constexpr subrange(I i, S s) requires (!StoreSize);
constexpr subrange(I i, S s, iter_difference_t<I> n)
requires (K == subrange_kind::sized);
template<not-same-as<subrange> R>
requires forwarding-range<R> &&
ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S>
constexpr subrange(R&& r) requires (!StoreSize || SizedRange<R>);
template<forwarding-range R>
requires ConvertibleTo<iterator_t<R>, I> && ConvertibleTo<sentinel_t<R>, S>
constexpr subrange(R&& r, iter_difference_t<I> n)
requires (K == subrange_kind::sized)
: subrange{ranges::begin(r), ranges::end(r), n}
{}
template<not-same-as<subrange> PairLike>
requires pair-like-convertible-to<PairLike, I, S>
constexpr subrange(PairLike&& r) requires (!StoreSize)
: subrange{std::get<0>(std::forward<PairLike>(r)),
std::get<1>(std::forward<PairLike>(r))}
{}
template<pair-like-convertible-to<I, S> PairLike>
constexpr subrange(PairLike&& r, iter_difference_t<I> n)
requires (K == subrange_kind::sized)
: subrange{std::get<0>(std::forward<PairLike>(r)),
std::get<1>(std::forward<PairLike>(r)), n}
{}
template<not-same-as<subrange> PairLike>
requires pair-like-convertible-from<PairLike, const I&, const S&>
constexpr operator PairLike() const;
constexpr I begin() const;
constexpr S end() const;
constexpr bool empty() const;
constexpr iter_difference_t<I> size() const
requires (K == subrange_kind::sized);
[[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const;
[[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
requires BidirectionalIterator<I>;
constexpr subrange& advance(iter_difference_t<I> n);
friend constexpr I begin(subrange&& r) { return r.begin(); }
friend constexpr S end(subrange&& r) { return r.end(); }
};
template<Iterator I, Sentinel<I> S>
subrange(I, S, iter_difference_t<I>) -> subrange<I, S, subrange_kind::sized>;
template<iterator-sentinel-pair P>
subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
template<iterator-sentinel-pair P>
subrange(P, iter_difference_t<tuple_element_t<0, P>>) ->
subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
template<forwarding-range R>
subrange(R&&) ->
subrange<iterator_t<R>, sentinel_t<R>,
(SizedRange<R> || SizedSentinel<sentinel_t<R>, iterator_t<R>>)
? subrange_kind::sized : subrange_kind::unsized>;
template<forwarding-range R>
subrange(R&&, iter_difference_t<iterator_t<R>>) ->
subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
template<size_t N, class I, class S, subrange_kind K>
requires (N < 2)
constexpr auto get(const subrange<I, S, K>& r);
}
namespace std {
using ranges::get;
}