14 #ifndef RANGES_V3_VIEW_IOTA_HPP
15 #define RANGES_V3_VIEW_IOTA_HPP
20 #include <type_traits>
30 #include <range/v3/utility/static_const.hpp>
34 #include <range/v3/detail/prologue.hpp>
36 RANGES_DIAGNOSTIC_PUSH
37 RANGES_DIAGNOSTIC_IGNORE_UNSIGNED_MATH
38 RANGES_DIAGNOSTIC_IGNORE_TRUNCATION
45 template<std::
size_t N,
typename =
void>
46 struct promote_as_signed_
50 static_assert(
sizeof(std::intmax_t) * CHAR_BIT >= N,
51 "Possible extended integral type?");
52 using difference_type = diffmax_t;
55 template<std::
size_t N>
56 struct promote_as_signed_<N, enable_if_t<(N < 16)>>
58 using difference_type = std::int_fast16_t;
61 template<std::
size_t N>
62 struct promote_as_signed_<N, enable_if_t<(N >= 16 && N < 32)>>
64 using difference_type = std::int_fast32_t;
67 template<std::
size_t N>
68 struct promote_as_signed_<N, enable_if_t<(N >= 32 && N < 64)>>
70 using difference_type = std::int_fast64_t;
75 std::is_integral<I>::value &&
sizeof(I) ==
sizeof(iter_difference_t<I>),
76 promote_as_signed_<
sizeof(iter_difference_t<I>) * CHAR_BIT>,
77 with_difference_type_<iter_difference_t<I>>>::difference_type;
83 CPP_requires(_decrementable_,
88 concepts::requires_<same_as<I&, decltype(--i)>>,
89 concepts::requires_<same_as<I, decltype(i--)>>
94 CPP_concept decrementable_ =
96 CPP_requires_ref(detail::_decrementable_, I);
101 CPP_requires(_advanceable_,
102 requires(I i, I
const j, iota_difference_t<I>
const n)
107 static_cast<I
>(j - n),
108 static_cast<I
>(j + n),
109 static_cast<I
>(n + j),
114 concepts::requires_<convertible_to<decltype(j - j), iota_difference_t<I>>>,
115 concepts::requires_<same_as<I&, decltype(i += n)>>,
116 concepts::requires_<same_as<I&, decltype(i -= n)>>
124 CPP_concept advanceable_ =
125 decrementable_<I> && totally_ordered<I> &&
126 CPP_requires_ref(detail::_advanceable_, I);
129 template(
typename I)(
130 requires (!unsigned_integral<I>))
131 void iota_advance_(I & i, iota_difference_t<I> n)
137 template(
typename Int)(
138 requires unsigned_integral<Int>)
139 void iota_advance_(Int & i, iota_difference_t<Int> n)
143 i +=
static_cast<Int
>(n);
145 i -=
static_cast<Int
>(-n);
148 template(
typename I)(
149 requires advanceable_<I> AND (!integral<I>))
150 iota_difference_t<I> iota_distance_(I
const & i, I
const & s)
152 return static_cast<iota_difference_t<I>
>(s - i);
155 template(
typename Int)(
156 requires signed_integral<Int>)
157 iota_difference_t<Int> iota_distance_(Int i0, Int i1)
160 return static_cast<iota_difference_t<Int>
>(
161 static_cast<iota_difference_t<Int>
>(i1) -
162 static_cast<iota_difference_t<Int>
>(i0));
165 template(
typename Int)(
166 requires unsigned_integral<Int>)
167 iota_difference_t<Int> iota_distance_(Int i0, Int i1)
170 return (i0 > i1) ?
static_cast<iota_difference_t<Int>
>(
171 -
static_cast<iota_difference_t<Int>
>(i0 - i1))
172 : static_cast<iota_difference_t<Int>>(i1 - i0);
181 template<
typename From,
typename To >
189 RANGES_NO_UNIQUE_ADDRESS To to_ = To();
193 using difference_type = detail::iota_difference_t<From>;
198 RANGES_NO_UNIQUE_ADDRESS To to_ = To();
203 RANGES_EXPECT(!done_);
208 RANGES_EXPECT(!done_);
219 auto equal(cursor
const & that)
const
221 requires equality_comparable<From>)
223 return that.from_ == from_ && that.done_ == done_;
228 requires detail::decrementable_<From>)
236 auto advance(difference_type n)
238 requires detail::advanceable_<From>)
242 RANGES_ENSURE(detail::iota_distance_(from_, to_) >= n - !done_);
243 detail::iota_advance_(
245 n - (done_ = (detail::iota_distance_(from_, to_) <= n - !done_)));
248 detail::iota_advance_(from_, n + std::exchange(done_,
false));
251 auto distance_to(cursor
const & that)
const
252 -> CPP_ret(difference_type)(
253 requires detail::advanceable_<From>)
255 using D = difference_type;
256 return static_cast<D
>(detail::iota_distance_(from_, that.from_)) +
257 ((D)that.done_ - (D)done_);
261 -> CPP_ret(difference_type)(
262 requires sized_sentinel_for<To, From>)
264 return difference_type(to_ - from_) + !done_;
269 constexpr cursor(From from, To to,
bool done =
false)
270 : from_(std::move(from))
276 cursor begin_cursor()
const
281 auto end_cursor()
const
283 requires same_as<From, To>)
285 return {to_, to_,
true};
288 auto end_cursor()
const
290 requires (!same_as<From, To>))
295 constexpr
void check_bounds_(std::true_type)
297 RANGES_EXPECT(from_ <= to_);
299 constexpr
void check_bounds_(std::false_type)
305 : from_(std::move(from))
308 check_bounds_(
meta::bool_<totally_ordered_with<From, To>>{});
312 template<
typename From,
typename To>
313 RANGES_INLINE_VAR constexpr
bool enable_borrowed_range<closed_iota_view<From, To>> =
316 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
317 template(
typename From,
typename To)(
318 requires weakly_incrementable<From> AND semiregular<To> AND
319 (!integral<From> || !integral<To> ||
320 std::is_signed<From>::value == std::is_signed<To>::value))
322 ->closed_iota_view<From, To>;
325 template<
typename From,
typename To >
328 same_as<To, unreachable_sentinel_t>
330 : std::is_integral<From>::value && std::is_integral<To>::value
337 RANGES_NO_UNIQUE_ADDRESS To to_ = To();
343 friend struct cursor;
344 RANGES_NO_UNIQUE_ADDRESS To to_;
347 sentinel() =
default;
348 constexpr
explicit sentinel(To to)
355 using difference_type = detail::iota_difference_t<From>;
369 bool equal(sentinel
const & that)
const
371 return from_ == that.to_;
374 auto equal(cursor
const & that)
const
376 requires equality_comparable<From>)
378 return that.from_ == from_;
383 requires detail::decrementable_<From>)
388 auto advance(difference_type n)
390 requires detail::advanceable_<From>)
392 detail::iota_advance_(from_, n);
398 auto distance_to(cursor
const & that)
const
399 -> CPP_ret(difference_type)(
400 requires detail::advanceable_<From>)
402 return detail::iota_distance_(from_, that.from_);
406 auto distance_to(sentinel
const & that)
const
407 -> CPP_ret(difference_type)(
408 requires sized_sentinel_for<To, From>)
410 return that.to_ - from_;
415 constexpr
explicit cursor(From from)
416 : from_(std::move(from))
419 cursor begin_cursor()
const
421 return cursor{from_};
424 auto CPP_fun(end_cursor)()(
const
425 requires(same_as<To, unreachable_sentinel_t>))
430 auto CPP_fun(end_cursor)()(
const
431 requires(!same_as<To, unreachable_sentinel_t>))
435 constexpr
void check_bounds_(std::true_type)
437 RANGES_EXPECT(from_ <= to_);
439 constexpr
void check_bounds_(std::false_type)
443 #ifdef RANGES_WORKAROUND_MSVC_934264
448 : from_(std::move(from))
451 : from_(std::move(from))
454 check_bounds_(
meta::bool_<totally_ordered_with<From, To>>{});
458 template<
typename From,
typename To>
459 RANGES_INLINE_VAR constexpr
bool enable_borrowed_range<iota_view<From, To>> =
true;
461 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
462 template(
typename From,
typename To)(
463 requires weakly_incrementable<From> AND semiregular<To> AND
464 (!integral<From> || !integral<To> ||
465 std::is_signed<From>::value == std::is_signed<To>::value))
467 ->iota_view<From, To>;
474 template(
typename From)(
475 requires weakly_incrementable<From>)
480 template(
typename From,
typename To)(
481 requires weakly_incrementable<From> AND semiregular<To> AND
482 detail::weakly_equality_comparable_with_<From, To> AND
483 (!integral<From> || !integral<To> ||
484 std::is_signed<From>::value == std::is_signed<To>::value))
487 return {std::move(from), std::move(to)};
493 template(
typename From,
typename To)(
494 requires weakly_incrementable<From> AND semiregular<To> AND
495 detail::weakly_equality_comparable_with_<From, To> AND
496 (!integral<From> || !integral<To> ||
497 std::is_signed<From>::value == std::is_signed<To>::value))
500 return {std::move(from), std::move(to)};
544 template(
typename Val)(
545 requires integral<Val>)
547 "This potentially confusing API is deprecated. Prefer to "
548 "explicitly specify the upper bound as with ranges::unreachable, as in "
549 "views::ints( n, unreachable )")
554 template(
typename Val)(
555 requires integral<Val>)
560 template(
typename Val)(
561 requires integral<Val>)
577 using ranges::views::iota;
583 #include <range/v3/detail/satisfy_boost_range.hpp>
587 RANGES_DIAGNOSTIC_POP
589 #include <range/v3/detail/epilogue.hpp>
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1148
_t< id< T > > id_t
An alias for type T.
Definition: meta.hpp:577
An iota view in a closed range.
Definition: iota.hpp:184
Definition: default_sentinel.hpp:26
Definition: unreachable_sentinel.hpp:27
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66