5 #ifndef VCCC_RANGES_SUBRANGE_HPP
6 #define VCCC_RANGES_SUBRANGE_HPP
10 #include <type_traits>
49 template<
typename From,
typename To>
50 struct convertible_to_non_slicing
52 convertible_to<From, To>,
55 negation< std::is_pointer<From> >,
56 negation< std::is_pointer<To> >
58 std::is_convertible<std::remove_pointer_t<From>(*)[], std::remove_pointer_t<To>(*)[]>
62 template<
typename T,
typename U>
63 struct different_from : negation<same_as<std::decay_t<T>, std::decay_t<U>>> {};
66 struct make_unsigned_like {};
68 struct make_unsigned_like<T, true> {
69 using type = std::make_unsigned_t<T>;
72 using make_unsigned_like_t =
typename make_unsigned_like<T>::type;
75 struct pair_like_convertible_from
78 negation< std::is_reference<T> >,
79 constructible_from<T, U, V>,
80 convertible_to_non_slicing<U, std::tuple_element_t<0, T>>,
81 convertible_to<V, std::tuple_element_t<1, T>>
84 template<
typename T,
typename U,
typename V>
85 struct pair_like_convertible_from<T, U, V, false> : std::false_type {};
88 struct borrowed_range_difference {
89 using type = range_difference_t<R>;
92 struct borrowed_range_difference<R, false> {};
94 using borrowed_range_difference_t =
typename borrowed_range_difference<R>::type;
101 struct is_subrange_constructible
103 input_or_output_iterator<I>,
106 bool_constant<(K == subrange_kind::sized)>,
107 negation< sized_sentinel_for<S, I> >
111 template<
typename I,
typename S,
bool Store >
112 struct subrange_size {
113 constexpr subrange_size() =
default;
115 constexpr subrange_size(in_place_t, U) noexcept {}
118 template<
typename I,
typename S>
119 struct subrange_size<I, S, true> {
120 constexpr subrange_size() =
default;
122 constexpr subrange_size(in_place_t, U n) : size_(n) {}
124 std::make_unsigned_t<iter_difference_t<I>> size_ = 0;
128 struct subrange_ctor_range
130 convertible_to_non_slicing<iterator_t<R>, I>,
131 convertible_to<sentinel_t<R>, S>
134 template<
typename I,
typename S,
typename R>
135 struct subrange_ctor_range<I, S, R, false> : std::false_type {};
150 , detail::subrange_size<I, S, (K == subrange_kind::sized && sized_sentinel_for<S, I>::value == false)>
153 using size_base = detail::subrange_size<I, S, store_size::value>;
161 template<
typename I2, std::enable_if_t<
conjunction<
162 detail::convertible_to_non_slicing<I2, I>,
166 : iterator_(
std::move(i)), sentinel_(
std::move(s)) {}
168 template<
typename I2, std::enable_if_t<
conjunction<
169 detail::convertible_to_non_slicing<I2, I>,
173 : size_base(
in_place, n), iterator_(
std::move(i)), sentinel_(
std::move(s)) {}
176 detail::different_from<subrange, R>,
177 detail::subrange_ctor_range<I, S, R>,
187 detail::subrange_ctor_range<I, S, R>,
194 template<
typename PairLike, std::enable_if_t<
conjunction<
196 detail::pair_like_convertible_from<PairLike, const I&, const S&>
198 constexpr
operator PairLike()
const {
199 return PairLike(iterator_, sentinel_);
210 return std::move(iterator_);
219 return iterator_ == sentinel_;
226 constexpr detail::make_unsigned_like_t<iter_difference_t<I>>
size()
const {
227 return static_cast<detail::make_unsigned_like_t<iter_difference_t<I>
>>(sentinel_ - iterator_);
234 constexpr detail::make_unsigned_like_t<iter_difference_t<I>>
size()
const {
235 return size_base::size_;
260 return std::move(*
this);
270 template<
typename I,
typename S, std::enable_if_t<
conjunction<
274 constexpr subrange<I, S>
279 template<
typename I,
typename S, std::enable_if_t<
conjunction<
283 constexpr subrange<I, S, subrange_kind::sized>
289 constexpr subrange<iterator_t<R>, sentinel_t<R>,
294 return {std::forward<R>(r)};
300 return {std::forward<R>(r), n};
304 #if __cplusplus >= 201703L
315 template<
typename I,
typename S>
317 subrange<I, S, ranges::subrange_kind::sized>;
331 struct is_size_storing_subrange;
333 template<
typename I,
typename S, subrange_kind K>
334 struct is_size_storing_subrange<
subrange<I, S, K>>
335 :
bool_constant<(K == subrange_kind::sized && sized_sentinel_for<S, I>::value == false)> {};
337 template<std::
size_t N>
340 template<>
struct get_subrange<0> {
341 template<
typename I,
typename S, subrange_kind K>
342 static constexpr
auto get(
const subrange<I, S, K>& r) {
345 template<
typename I,
typename S, subrange_kind K>
346 static constexpr
auto get(subrange<I, S, K>&& r) {
347 return std::move(r.begin());
351 template<>
struct get_subrange<1> {
352 template<
typename I,
typename S, subrange_kind K>
353 auto get(
const subrange<I, S, K>& r) {
356 template<
typename I,
typename S, subrange_kind K>
357 auto get(subrange<I, S, K>&& r) {
358 return std::move(r.end());
363 struct is_subrange : std::false_type {};
364 template<
typename I,
typename S, subrange_kind K>
365 struct is_subrange<
subrange<I, S, K>> : std::true_type {};
369 template<std::size_t N,
typename I,
typename S,
subrange_kind K,
375 template<std::size_t N,
typename I,
typename S,
subrange_kind K,
376 std::enable_if_t<(N < 2), int> = 0>
381 template<
typename I,
typename S, subrange_kind K>
390 template<
typename I,
typename S, ranges::subrange_kind K>
391 struct tuple_like_uncvref<ranges::subrange<I, S, K>> : std::true_type {};
397 template<
typename I,
typename S, vccc::ranges::subrange_kind K>
398 struct std::tuple_size<
vccc::ranges::subrange<I, S, K>> : std::integral_constant<std::size_t, 2> {};
404 template<
typename I,
typename S, vccc::ranges::subrange_kind K>
405 struct tuple_element<0,
vccc::ranges::subrange<I, S, K>> {
using type = I; };
406 template<
typename I,
typename S, vccc::ranges::subrange_kind K>
407 struct tuple_element<0, const
vccc::ranges::subrange<I, S, K>> {
using type = I; };
408 template<
typename I,
typename S, vccc::ranges::subrange_kind K>
409 struct tuple_element<1,
vccc::ranges::subrange<I, S, K>> {
using type = S; };
410 template<
typename I,
typename S, vccc::ranges::subrange_kind K>
411 struct tuple_element<1, const
vccc::ranges::subrange<I, S, K>> {
using type = S; };
Definition: subrange.hpp:151
constexpr VCCC_NODISCARD subrange_kind next(iter_difference_t< I > n=1) const &
Definition: subrange.hpp:251
constexpr subrange(R &&r)
Definition: subrange.hpp:183
constexpr S end() const
Definition: subrange.hpp:213
constexpr VCCC_NODISCARD subrange_kind prev(iter_difference_t< I > n=1) const
Definition: subrange.hpp:244
constexpr subrange(R &&r, detail::make_unsigned_like_t< iter_difference_t< I >> n)
Definition: subrange.hpp:190
constexpr subrange(I2 i, S s, detail::make_unsigned_like_t< iter_difference_t< I >> n)
Definition: subrange.hpp:172
constexpr VCCC_NODISCARD I begin()
Definition: subrange.hpp:209
constexpr I begin() const
Definition: subrange.hpp:204
constexpr subrange & advance(iter_difference_t< I > n)
Definition: subrange.hpp:238
constexpr detail::make_unsigned_like_t< iter_difference_t< I > > size() const
Definition: subrange.hpp:226
constexpr bool empty() const
Definition: subrange.hpp:217
constexpr VCCC_NODISCARD subrange_kind next(iter_difference_t< I > n=1) &&
Definition: subrange.hpp:258
constexpr subrange(I2 i, S s)
Definition: subrange.hpp:165
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
constexpr VCCC_INLINE_OR_STATIC detail::advance_niebloid advance
Definition: advance.hpp:158
typename iter_difference< T >::type iter_difference_t
Computes the difference type of T
Definition: iter_difference_t.hpp:49
constexpr auto get(subrange< I, S, K > &&r)
Definition: subrange.hpp:377
constexpr auto get(const subrange< I, S, K > &r)
Definition: subrange.hpp:371
subrange_kind
Definition: subrange_kind.hpp:18
typename sentinel< R >::type sentinel_t
Definition: sentinel_t.hpp:29
typename ranges::iterator< T >::type iterator_t
Definition: iterator_t.hpp:32
constexpr subrange< I, S > make_subrange(I i, S s)
Definition: subrange.hpp:275
typename range_difference< R >::type range_difference_t
Used to obtain the difference type of the iterator type of range type R.
Definition: range_difference_t.hpp:41
std::integral_constant< bool, v > bool_constant
Definition: bool_constant.hpp:19
constexpr VCCC_INLINE_OR_STATIC in_place_t in_place
Definition: in_place.hpp:47
Definition: matrix.hpp:495
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
#define VCCC_NODISCARD
Definition: nodiscard.hpp:14
I type
Definition: subrange.hpp:407
I type
Definition: subrange.hpp:405
S type
Definition: subrange.hpp:411
S type
Definition: subrange.hpp:409
Definition: conjunction.hpp:22
Definition: disjunction.hpp:22
Definition: negation.hpp:23
Definition: enable_borrowed_range.hpp:17
specifies that a range knows its size in constant time
Definition: sized_range.hpp:38
Definition: sentinel_for.hpp:24
specifies that the - operator can be applied to an iterator and a sentinel to calculate their differe...
Definition: sized_sentinel_for.hpp:75