14#ifndef RANGES_V3_VIEW_IOTA_HPP
15#define RANGES_V3_VIEW_IOTA_HPP
30#include <range/v3/utility/static_const.hpp>
34#include <range/v3/detail/prologue.hpp>
37RANGES_DIAGNOSTIC_IGNORE_UNSIGNED_MATH
38RANGES_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)(
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)(
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)(
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)(
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)(
480 template(
typename From,
typename To)(
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)(
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)};
506 RANGES_INLINE_VARIABLE(
iota_fn, iota)
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>)
570 RANGES_INLINE_VARIABLE(
ints_fn, ints)
577 using ranges::views::iota;
583#include <range/v3/detail/satisfy_boost_range.hpp>
589#include <range/v3/detail/epilogue.hpp>
The sized_sentinel_for concept.
The weakly_incrementable concept.
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