cycle.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /// \file cycle.hpp
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. // Copyright Gonzalo Brito Gadeschi 2015
  6. // Copyright Casey Carter 2015
  7. //
  8. // Use, modification and distribution is subject to the
  9. // Boost Software License, Version 1.0. (See accompanying
  10. // file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // Project home: https://github.com/ericniebler/range-v3
  14. //
  15. #ifndef RANGES_V3_VIEW_CYCLE_HPP
  16. #define RANGES_V3_VIEW_CYCLE_HPP
  17. #include <type_traits>
  18. #include <utility>
  19. #include <meta/meta.hpp>
  20. #include <range/v3/range_fwd.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/iterator/unreachable_sentinel.hpp>
  23. #include <range/v3/range/access.hpp>
  24. #include <range/v3/range/concepts.hpp>
  25. #include <range/v3/range/primitives.hpp>
  26. #include <range/v3/range/traits.hpp>
  27. #include <range/v3/utility/box.hpp>
  28. #include <range/v3/utility/get.hpp>
  29. #include <range/v3/utility/optional.hpp>
  30. #include <range/v3/utility/static_const.hpp>
  31. #include <range/v3/view/all.hpp>
  32. #include <range/v3/view/facade.hpp>
  33. #include <range/v3/view/view.hpp>
  34. #include <range/v3/detail/prologue.hpp>
  35. namespace ranges
  36. {
  37. /// \addtogroup group-views
  38. /// @{
  39. template<typename Rng, bool /* = (bool) is_infinite<Rng>() */>
  40. struct RANGES_EMPTY_BASES cycled_view
  41. : view_facade<cycled_view<Rng>, infinite>
  42. , private detail::non_propagating_cache<iterator_t<Rng>, cycled_view<Rng>,
  43. !common_range<Rng>>
  44. {
  45. private:
  46. CPP_assert(forward_range<Rng> && !is_infinite<Rng>::value);
  47. friend range_access;
  48. Rng rng_;
  49. using cache_t = detail::non_propagating_cache<iterator_t<Rng>, cycled_view<Rng>,
  50. !common_range<Rng>>;
  51. template<bool IsConst>
  52. struct cursor
  53. {
  54. private:
  55. friend struct cursor<!IsConst>;
  56. template<typename T>
  57. using constify_if = meta::const_if_c<IsConst, T>;
  58. using cycled_view_t = constify_if<cycled_view>;
  59. using CRng = constify_if<Rng>;
  60. using iterator = iterator_t<CRng>;
  61. cycled_view_t * rng_{};
  62. iterator it_{};
  63. std::intmax_t n_ = 0;
  64. iterator get_end_(std::true_type, bool = false) const
  65. {
  66. return ranges::end(rng_->rng_);
  67. }
  68. template<bool CanBeEmpty = false>
  69. iterator get_end_(std::false_type, meta::bool_<CanBeEmpty> = {}) const
  70. {
  71. auto & end_ = static_cast<cache_t &>(*rng_);
  72. RANGES_EXPECT(CanBeEmpty || end_);
  73. if(CanBeEmpty && !end_)
  74. end_ = ranges::next(it_, ranges::end(rng_->rng_));
  75. return *end_;
  76. }
  77. void set_end_(std::true_type) const
  78. {}
  79. void set_end_(std::false_type) const
  80. {
  81. auto & end_ = static_cast<cache_t &>(*rng_);
  82. if(!end_)
  83. end_ = it_;
  84. }
  85. public:
  86. cursor() = default;
  87. cursor(cycled_view_t * rng)
  88. : rng_(rng)
  89. , it_(ranges::begin(rng->rng_))
  90. {}
  91. template(bool Other)(
  92. requires IsConst AND CPP_NOT(Other)) //
  93. cursor(cursor<Other> that)
  94. : rng_(that.rng_)
  95. , it_(std::move(that.it_))
  96. {}
  97. // clang-format off
  98. auto CPP_auto_fun(read)()(const)
  99. (
  100. return *it_
  101. )
  102. // clang-format on
  103. CPP_member
  104. auto equal(cursor const & pos) const //
  105. -> CPP_ret(bool)(
  106. requires equality_comparable<iterator>)
  107. {
  108. RANGES_EXPECT(rng_ == pos.rng_);
  109. return n_ == pos.n_ && it_ == pos.it_;
  110. }
  111. void next()
  112. {
  113. auto const last = ranges::end(rng_->rng_);
  114. RANGES_EXPECT(it_ != last);
  115. if(++it_ == last)
  116. {
  117. ++n_;
  118. this->set_end_(meta::bool_<(bool)common_range<CRng>>{});
  119. it_ = ranges::begin(rng_->rng_);
  120. }
  121. }
  122. CPP_member
  123. auto prev() //
  124. -> CPP_ret(void)(
  125. requires bidirectional_range<CRng>)
  126. {
  127. if(it_ == ranges::begin(rng_->rng_))
  128. {
  129. RANGES_EXPECT(n_ > 0); // decrementing the begin iterator?!
  130. --n_;
  131. it_ = this->get_end_(meta::bool_<(bool)common_range<CRng>>{});
  132. }
  133. --it_;
  134. }
  135. template(typename Diff)(
  136. requires random_access_range<CRng> AND
  137. detail::integer_like_<Diff>)
  138. void advance(Diff n)
  139. {
  140. auto const first = ranges::begin(rng_->rng_);
  141. auto const last = this->get_end_(meta::bool_<(bool)common_range<CRng>>{},
  142. meta::bool_<true>());
  143. auto const dist = last - first;
  144. auto const d = it_ - first;
  145. auto const off = (d + n) % dist;
  146. n_ += (d + n) / dist;
  147. RANGES_EXPECT(n_ >= 0);
  148. using D = range_difference_t<Rng>;
  149. it_ = first + static_cast<D>(off < 0 ? off + dist : off);
  150. }
  151. CPP_auto_member
  152. auto CPP_fun(distance_to)(cursor const & that)(const //
  153. requires sized_sentinel_for<iterator, iterator>)
  154. {
  155. RANGES_EXPECT(that.rng_ == rng_);
  156. auto const first = ranges::begin(rng_->rng_);
  157. auto const last = this->get_end_(meta::bool_<(bool)common_range<Rng>>{},
  158. meta::bool_<true>());
  159. auto const dist = last - first;
  160. return (that.n_ - n_) * dist + (that.it_ - it_);
  161. }
  162. };
  163. CPP_member
  164. auto begin_cursor() //
  165. -> CPP_ret(cursor<false>)(
  166. requires (!simple_view<Rng>() || !common_range<Rng const>))
  167. {
  168. return {this};
  169. }
  170. CPP_member
  171. auto begin_cursor() const //
  172. -> CPP_ret(cursor<true>)(
  173. requires common_range<Rng const>)
  174. {
  175. return {this};
  176. }
  177. unreachable_sentinel_t end_cursor() const
  178. {
  179. return unreachable;
  180. }
  181. public:
  182. cycled_view() = default;
  183. /// \pre <tt>!empty(rng)</tt>
  184. explicit cycled_view(Rng rng)
  185. : rng_(std::move(rng))
  186. {
  187. RANGES_EXPECT(!ranges::empty(rng_));
  188. }
  189. };
  190. template<typename Rng>
  191. struct cycled_view<Rng, true> : identity_adaptor<Rng>
  192. {
  193. CPP_assert(is_infinite<Rng>::value);
  194. using identity_adaptor<Rng>::identity_adaptor;
  195. };
  196. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  197. template<typename Rng>
  198. cycled_view(Rng &&) //
  199. -> cycled_view<views::all_t<Rng>>;
  200. #endif
  201. namespace views
  202. {
  203. /// Returns an infinite range that endlessly repeats the source
  204. /// range.
  205. struct cycle_fn
  206. {
  207. /// \pre <tt>!empty(rng)</tt>
  208. template(typename Rng)(
  209. requires viewable_range<Rng> AND forward_range<Rng>)
  210. cycled_view<all_t<Rng>> operator()(Rng && rng) const
  211. {
  212. return cycled_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
  213. }
  214. };
  215. /// \relates cycle_fn
  216. /// \ingroup group-views
  217. RANGES_INLINE_VARIABLE(view_closure<cycle_fn>, cycle)
  218. } // namespace views
  219. /// @}
  220. } // namespace ranges
  221. #include <range/v3/detail/epilogue.hpp>
  222. #include <range/v3/detail/satisfy_boost_range.hpp>
  223. RANGES_SATISFY_BOOST_RANGE(::ranges::cycled_view)
  224. #endif