iota.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_IOTA_HPP
  14. #define RANGES_V3_VIEW_IOTA_HPP
  15. #include <climits>
  16. #include <cstdint>
  17. #include <limits>
  18. #include <type_traits>
  19. #include <meta/meta.hpp>
  20. #include <concepts/concepts.hpp>
  21. #include <range/v3/range_fwd.hpp>
  22. #include <range/v3/iterator/default_sentinel.hpp>
  23. #include <range/v3/iterator/diffmax_t.hpp>
  24. #include <range/v3/utility/static_const.hpp>
  25. #include <range/v3/view/delimit.hpp>
  26. #include <range/v3/view/facade.hpp>
  27. #include <range/v3/detail/prologue.hpp>
  28. RANGES_DIAGNOSTIC_PUSH
  29. RANGES_DIAGNOSTIC_IGNORE_UNSIGNED_MATH
  30. RANGES_DIAGNOSTIC_IGNORE_TRUNCATION
  31. namespace ranges
  32. {
  33. /// \cond
  34. namespace detail
  35. {
  36. template<std::size_t N, typename = void>
  37. struct promote_as_signed_
  38. {
  39. // This shouldn't cause us to LOSE precision, but maybe it doesn't
  40. // net us any either.
  41. static_assert(sizeof(std::intmax_t) * CHAR_BIT >= N,
  42. "Possible extended integral type?");
  43. using difference_type = diffmax_t;
  44. };
  45. template<std::size_t N>
  46. struct promote_as_signed_<N, enable_if_t<(N < 16)>>
  47. {
  48. using difference_type = std::int_fast16_t;
  49. };
  50. template<std::size_t N>
  51. struct promote_as_signed_<N, enable_if_t<(N >= 16 && N < 32)>>
  52. {
  53. using difference_type = std::int_fast32_t;
  54. };
  55. template<std::size_t N>
  56. struct promote_as_signed_<N, enable_if_t<(N >= 32 && N < 64)>>
  57. {
  58. using difference_type = std::int_fast64_t;
  59. };
  60. template<typename I>
  61. using iota_difference_t = typename meta::conditional_t<
  62. std::is_integral<I>::value && sizeof(I) == sizeof(iter_difference_t<I>),
  63. promote_as_signed_<sizeof(iter_difference_t<I>) * CHAR_BIT>,
  64. with_difference_type_<iter_difference_t<I>>>::difference_type;
  65. // clang-format off
  66. /// \concept _decrementable_
  67. /// \brief The \c _decrementable_ concept
  68. template<typename I>
  69. CPP_requires(_decrementable_,
  70. requires(I i) //
  71. (
  72. --i,
  73. i--,
  74. concepts::requires_<same_as<I&, decltype(--i)>>,
  75. concepts::requires_<same_as<I, decltype(i--)>>
  76. ));
  77. /// \concept decrementable_
  78. /// \brief The \c decrementable_ concept
  79. template<typename I>
  80. CPP_concept decrementable_ =
  81. incrementable<I> &&
  82. CPP_requires_ref(detail::_decrementable_, I);
  83. /// \concept _advanceable_
  84. /// \brief The \c _advanceable_ concept
  85. template<typename I>
  86. CPP_requires(_advanceable_,
  87. requires(I i, I const j, iota_difference_t<I> const n) //
  88. (
  89. j - j,
  90. i += n,
  91. i -= n,
  92. static_cast<I>(j - n),
  93. static_cast<I>(j + n),
  94. static_cast<I>(n + j),
  95. // NOT TO SPEC:
  96. // Unsigned integers are advanceable, but subtracting them results in
  97. // an unsigned integral, which is not the same as the difference type,
  98. // which is signed.
  99. concepts::requires_<convertible_to<decltype(j - j), iota_difference_t<I>>>,
  100. concepts::requires_<same_as<I&, decltype(i += n)>>,
  101. concepts::requires_<same_as<I&, decltype(i -= n)>> //,
  102. // concepts::requires_<convertible_to<decltype(i - n), I>>,
  103. // concepts::requires_<convertible_to<decltype(i + n), I>>,
  104. // concepts::requires_<convertible_to<decltype(n + i), I>>
  105. ));
  106. /// \concept advanceable_
  107. /// \brief The \c advanceable_ concept
  108. template<typename I>
  109. CPP_concept advanceable_ =
  110. decrementable_<I> && totally_ordered<I> &&
  111. CPP_requires_ref(detail::_advanceable_, I);
  112. // clang-format on
  113. template(typename I)(
  114. requires (!unsigned_integral<I>)) //
  115. void iota_advance_(I & i, iota_difference_t<I> n)
  116. {
  117. // TODO: bounds-check this
  118. i += n;
  119. }
  120. template(typename Int)(
  121. requires unsigned_integral<Int>)
  122. void iota_advance_(Int & i, iota_difference_t<Int> n)
  123. {
  124. // TODO: bounds-check this
  125. if(n >= 0)
  126. i += static_cast<Int>(n);
  127. else
  128. i -= static_cast<Int>(-n);
  129. }
  130. template(typename I)(
  131. requires advanceable_<I> AND (!integral<I>)) //
  132. iota_difference_t<I> iota_distance_(I const & i, I const & s)
  133. {
  134. return static_cast<iota_difference_t<I>>(s - i);
  135. }
  136. template(typename Int)(
  137. requires signed_integral<Int>)
  138. iota_difference_t<Int> iota_distance_(Int i0, Int i1)
  139. {
  140. // TODO: bounds-check this
  141. return static_cast<iota_difference_t<Int>>(
  142. static_cast<iota_difference_t<Int>>(i1) -
  143. static_cast<iota_difference_t<Int>>(i0));
  144. }
  145. template(typename Int)(
  146. requires unsigned_integral<Int>)
  147. iota_difference_t<Int> iota_distance_(Int i0, Int i1)
  148. {
  149. // TODO: bounds-check this
  150. return (i0 > i1) ? static_cast<iota_difference_t<Int>>(
  151. -static_cast<iota_difference_t<Int>>(i0 - i1))
  152. : static_cast<iota_difference_t<Int>>(i1 - i0);
  153. }
  154. } // namespace detail
  155. /// \endcond
  156. /// \addtogroup group-views
  157. /// @{
  158. /// An iota view in a closed range
  159. template<typename From, typename To /* = From */>
  160. struct RANGES_EMPTY_BASES closed_iota_view
  161. : view_facade<closed_iota_view<From, To>, finite>
  162. {
  163. private:
  164. friend range_access;
  165. From from_ = From();
  166. RANGES_NO_UNIQUE_ADDRESS To to_ = To();
  167. struct cursor
  168. {
  169. using difference_type = detail::iota_difference_t<From>;
  170. private:
  171. friend range_access;
  172. From from_ = From();
  173. RANGES_NO_UNIQUE_ADDRESS To to_ = To();
  174. bool done_ = false;
  175. From read() const
  176. {
  177. RANGES_EXPECT(!done_);
  178. return from_;
  179. }
  180. void next()
  181. {
  182. RANGES_EXPECT(!done_);
  183. if(from_ == to_)
  184. done_ = true;
  185. else
  186. ++from_;
  187. }
  188. bool equal(default_sentinel_t) const
  189. {
  190. return done_;
  191. }
  192. CPP_member
  193. auto equal(cursor const & that) const //
  194. -> CPP_ret(bool)(
  195. requires equality_comparable<From>)
  196. {
  197. return that.from_ == from_ && that.done_ == done_;
  198. }
  199. CPP_member
  200. auto prev() //
  201. -> CPP_ret(void)(
  202. requires detail::decrementable_<From>)
  203. {
  204. if(done_)
  205. done_ = false;
  206. else
  207. --from_;
  208. }
  209. CPP_member
  210. auto advance(difference_type n) //
  211. -> CPP_ret(void)(
  212. requires detail::advanceable_<From>)
  213. {
  214. if(n > 0)
  215. {
  216. RANGES_ENSURE(detail::iota_distance_(from_, to_) >= n - !done_);
  217. detail::iota_advance_(
  218. from_,
  219. n - (done_ = (detail::iota_distance_(from_, to_) <= n - !done_)));
  220. }
  221. else if(n < 0)
  222. detail::iota_advance_(from_, n + std::exchange(done_, false));
  223. }
  224. CPP_member
  225. auto distance_to(cursor const & that) const //
  226. -> CPP_ret(difference_type)(
  227. requires detail::advanceable_<From>)
  228. {
  229. using D = difference_type;
  230. return static_cast<D>(detail::iota_distance_(from_, that.from_)) +
  231. ((D)that.done_ - (D)done_);
  232. }
  233. CPP_member
  234. auto distance_to(default_sentinel_t) const //
  235. -> CPP_ret(difference_type)(
  236. requires sized_sentinel_for<To, From>)
  237. {
  238. return difference_type(to_ - from_) + !done_;
  239. }
  240. public:
  241. cursor() = default;
  242. constexpr cursor(From from, To to, bool done = false)
  243. : from_(std::move(from))
  244. , to_(std::move(to))
  245. , done_(done)
  246. {}
  247. };
  248. cursor begin_cursor() const
  249. {
  250. return {from_, to_};
  251. }
  252. CPP_member
  253. auto end_cursor() const //
  254. -> CPP_ret(cursor)(
  255. requires same_as<From, To>)
  256. {
  257. return {to_, to_, true};
  258. }
  259. CPP_member
  260. auto end_cursor() const //
  261. -> CPP_ret(default_sentinel_t)(
  262. requires (!same_as<From, To>))
  263. {
  264. return {};
  265. }
  266. constexpr void check_bounds_(std::true_type)
  267. {
  268. RANGES_EXPECT(from_ <= to_);
  269. }
  270. constexpr void check_bounds_(std::false_type)
  271. {}
  272. public:
  273. closed_iota_view() = default;
  274. constexpr closed_iota_view(meta::id_t<From> from, meta::id_t<To> to)
  275. : from_(std::move(from))
  276. , to_(std::move(to))
  277. {
  278. check_bounds_(meta::bool_<totally_ordered_with<From, To>>{});
  279. }
  280. };
  281. template<typename From, typename To>
  282. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<closed_iota_view<From, To>> =
  283. true;
  284. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  285. template(typename From, typename To)(
  286. requires weakly_incrementable<From> AND semiregular<To> AND
  287. (!integral<From> || !integral<To> ||
  288. std::is_signed<From>::value == std::is_signed<To>::value)) //
  289. closed_iota_view(From, To)
  290. ->closed_iota_view<From, To>;
  291. #endif
  292. template<typename From, typename To /* = unreachable_sentinel_t*/>
  293. struct RANGES_EMPTY_BASES iota_view
  294. : view_facade<iota_view<From, To>,
  295. same_as<To, unreachable_sentinel_t>
  296. ? infinite
  297. : std::is_integral<From>::value && std::is_integral<To>::value
  298. ? finite
  299. : unknown>
  300. {
  301. private:
  302. friend range_access;
  303. From from_ = From();
  304. RANGES_NO_UNIQUE_ADDRESS To to_ = To();
  305. struct cursor;
  306. struct sentinel
  307. {
  308. private:
  309. friend struct cursor;
  310. RANGES_NO_UNIQUE_ADDRESS To to_;
  311. public:
  312. sentinel() = default;
  313. constexpr explicit sentinel(To to)
  314. : to_(std::move(to))
  315. {}
  316. };
  317. struct cursor
  318. {
  319. using difference_type = detail::iota_difference_t<From>;
  320. private:
  321. friend range_access;
  322. From from_;
  323. From read() const
  324. {
  325. return from_;
  326. }
  327. void next()
  328. {
  329. ++from_;
  330. }
  331. bool equal(sentinel const & that) const
  332. {
  333. return from_ == that.to_;
  334. }
  335. CPP_member
  336. auto equal(cursor const & that) const //
  337. -> CPP_ret(bool)(
  338. requires equality_comparable<From>)
  339. {
  340. return that.from_ == from_;
  341. }
  342. CPP_member
  343. auto prev() //
  344. -> CPP_ret(void)(
  345. requires detail::decrementable_<From>)
  346. {
  347. --from_;
  348. }
  349. CPP_member
  350. auto advance(difference_type n) //
  351. -> CPP_ret(void)(
  352. requires detail::advanceable_<From>)
  353. {
  354. detail::iota_advance_(from_, n);
  355. }
  356. // Not to spec: TODO the relational operators will effectively be constrained
  357. // with Advanceable, but they should be constrained with totally_ordered.
  358. // Reimplement iota_view without view_facade or basic_iterator.
  359. CPP_member
  360. auto distance_to(cursor const & that) const //
  361. -> CPP_ret(difference_type)(
  362. requires detail::advanceable_<From>)
  363. {
  364. return detail::iota_distance_(from_, that.from_);
  365. }
  366. // Extension: see https://github.com/ericniebler/stl2/issues/613
  367. CPP_member
  368. auto distance_to(sentinel const & that) const //
  369. -> CPP_ret(difference_type)(
  370. requires sized_sentinel_for<To, From>)
  371. {
  372. return that.to_ - from_;
  373. }
  374. public:
  375. cursor() = default;
  376. constexpr explicit cursor(From from)
  377. : from_(std::move(from))
  378. {}
  379. };
  380. cursor begin_cursor() const
  381. {
  382. return cursor{from_};
  383. }
  384. CPP_auto_member
  385. auto CPP_fun(end_cursor)()(const //
  386. requires(same_as<To, unreachable_sentinel_t>))
  387. {
  388. return unreachable;
  389. }
  390. CPP_auto_member
  391. auto CPP_fun(end_cursor)()(const //
  392. requires(!same_as<To, unreachable_sentinel_t>))
  393. {
  394. return meta::conditional_t<same_as<From, To>, cursor, sentinel>{to_};
  395. }
  396. constexpr void check_bounds_(std::true_type)
  397. {
  398. RANGES_EXPECT(from_ <= to_);
  399. }
  400. constexpr void check_bounds_(std::false_type)
  401. {}
  402. public:
  403. #ifdef RANGES_WORKAROUND_MSVC_934264
  404. constexpr
  405. #endif // RANGES_WORKAROUND_MSVC_934264
  406. iota_view() = default;
  407. constexpr explicit iota_view(From from)
  408. : from_(std::move(from))
  409. {}
  410. constexpr iota_view(meta::id_t<From> from, meta::id_t<To> to)
  411. : from_(std::move(from))
  412. , to_(std::move(to))
  413. {
  414. check_bounds_(meta::bool_<totally_ordered_with<From, To>>{});
  415. }
  416. };
  417. template<typename From, typename To>
  418. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<iota_view<From, To>> = true;
  419. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  420. template(typename From, typename To)(
  421. requires weakly_incrementable<From> AND semiregular<To> AND
  422. (!integral<From> || !integral<To> ||
  423. std::is_signed<From>::value == std::is_signed<To>::value)) //
  424. iota_view(From, To)
  425. ->iota_view<From, To>;
  426. #endif
  427. namespace views
  428. {
  429. struct iota_fn
  430. {
  431. template(typename From)(
  432. requires weakly_incrementable<From>)
  433. iota_view<From> operator()(From value) const
  434. {
  435. return iota_view<From>{std::move(value)};
  436. }
  437. template(typename From, typename To)(
  438. requires weakly_incrementable<From> AND semiregular<To> AND
  439. detail::weakly_equality_comparable_with_<From, To> AND
  440. (!integral<From> || !integral<To> ||
  441. std::is_signed<From>::value == std::is_signed<To>::value)) //
  442. iota_view<From, To> operator()(From from, To to) const
  443. {
  444. return {std::move(from), std::move(to)};
  445. }
  446. };
  447. struct closed_iota_fn
  448. {
  449. template(typename From, typename To)(
  450. requires weakly_incrementable<From> AND semiregular<To> AND
  451. detail::weakly_equality_comparable_with_<From, To> AND
  452. (!integral<From> || !integral<To> ||
  453. std::is_signed<From>::value == std::is_signed<To>::value)) //
  454. closed_iota_view<From, To> operator()(From from, To to) const
  455. {
  456. return {std::move(from), std::move(to)};
  457. }
  458. };
  459. /// \relates iota_fn
  460. /// \ingroup group-views
  461. RANGES_INLINE_VARIABLE(iota_fn, iota)
  462. /// \relates closed_iota_fn
  463. /// \ingroup group-views
  464. RANGES_INLINE_VARIABLE(closed_iota_fn, closed_iota)
  465. /// # ranges::views::ints
  466. /// The ints view returns a range of monotonically increasing ints.
  467. ///
  468. /// ## Example
  469. /// \snippet example/view/ints.cpp ints example
  470. ///
  471. /// ### Output
  472. /// \include example/view/ints_golden.txt
  473. ///
  474. /// ## Syntax
  475. /// ```cpp
  476. /// auto output_range = ranges::views::ints(lower_bound, upper_bound);
  477. /// ```
  478. ///
  479. /// ## Parameters
  480. /// <pre><b>lower_bound</b></pre>
  481. /// - Optional lower bound
  482. ///
  483. /// <pre><b>upper_bound</b></pre>
  484. /// - Exclusive upper bound
  485. /// - Required when `lower_bound` is specified
  486. /// - To create an infinite range with a `lower_bound`, use
  487. /// `ranges::unreachable` as the `upper_bound`
  488. ///
  489. /// <pre><b>output_range</b></pre>
  490. /// - Range of monotonically increasing ints
  491. /// - When an `upper_bound` is not specified, the range is quasi-infinite
  492. ///
  493. struct ints_fn : iota_view<int>
  494. {
  495. ints_fn() = default;
  496. template(typename Val)(
  497. requires integral<Val>)
  498. RANGES_DEPRECATED(
  499. "This potentially confusing API is deprecated. Prefer to "
  500. "explicitly specify the upper bound as with ranges::unreachable, as in "
  501. "views::ints( n, unreachable )")
  502. constexpr iota_view<Val> operator()(Val value) const //
  503. {
  504. return iota_view<Val>{value};
  505. }
  506. template(typename Val)(
  507. requires integral<Val>)
  508. constexpr iota_view<Val> operator()(Val value, unreachable_sentinel_t) const
  509. {
  510. return iota_view<Val>{value};
  511. }
  512. template(typename Val)(
  513. requires integral<Val>)
  514. constexpr iota_view<Val, Val> operator()(Val from, Val to) const
  515. {
  516. return {from, to};
  517. }
  518. };
  519. /// \relates ints_fn
  520. /// \ingroup group-views
  521. RANGES_INLINE_VARIABLE(ints_fn, ints)
  522. } // namespace views
  523. namespace cpp20
  524. {
  525. namespace views
  526. {
  527. using ranges::views::iota;
  528. }
  529. } // namespace cpp20
  530. /// @}
  531. } // namespace ranges
  532. #include <range/v3/detail/satisfy_boost_range.hpp>
  533. RANGES_SATISFY_BOOST_RANGE(::ranges::closed_iota_view)
  534. RANGES_SATISFY_BOOST_RANGE(::ranges::iota_view)
  535. RANGES_DIAGNOSTIC_POP
  536. #include <range/v3/detail/epilogue.hpp>
  537. #endif