intersperse.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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_INTERSPERSE_HPP
  14. #define RANGES_V3_VIEW_INTERSPERSE_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/functional/bind_back.hpp>
  20. #include <range/v3/iterator/operations.hpp>
  21. #include <range/v3/range/access.hpp>
  22. #include <range/v3/range/concepts.hpp>
  23. #include <range/v3/range/primitives.hpp>
  24. #include <range/v3/range/traits.hpp>
  25. #include <range/v3/utility/static_const.hpp>
  26. #include <range/v3/view/adaptor.hpp>
  27. #include <range/v3/view/view.hpp>
  28. #include <range/v3/detail/prologue.hpp>
  29. namespace ranges
  30. {
  31. /// \addtogroup group-views
  32. /// @{
  33. template<typename Rng>
  34. struct intersperse_view
  35. : view_adaptor<intersperse_view<Rng>, Rng,
  36. (range_cardinality<Rng>::value > 0)
  37. ? static_cast<cardinality>(range_cardinality<Rng>::value * 2 - 1)
  38. : range_cardinality<Rng>::value>
  39. {
  40. intersperse_view() = default;
  41. constexpr intersperse_view(Rng rng, range_value_t<Rng> val)
  42. : intersperse_view::view_adaptor{detail::move(rng)}
  43. , val_(detail::move(val))
  44. {}
  45. CPP_auto_member
  46. constexpr auto CPP_fun(size)()(const //
  47. requires sized_range<Rng const>)
  48. {
  49. auto const n = ranges::size(this->base());
  50. return n ? n * 2 - 1 : 0;
  51. }
  52. CPP_auto_member
  53. constexpr auto CPP_fun(size)()(
  54. requires sized_range<Rng>)
  55. {
  56. auto const n = ranges::size(this->base());
  57. return n ? n * 2 - 1 : 0;
  58. }
  59. private:
  60. friend range_access;
  61. template<bool Const>
  62. struct cursor_adaptor : adaptor_base
  63. {
  64. private:
  65. friend struct cursor_adaptor<!Const>;
  66. using CRng = meta::const_if_c<Const, Rng>;
  67. bool toggle_ = false;
  68. range_value_t<Rng> val_;
  69. public:
  70. cursor_adaptor() = default;
  71. constexpr explicit cursor_adaptor(range_value_t<Rng> const & val)
  72. : val_{val}
  73. {}
  74. template(bool Other)(
  75. requires Const AND CPP_NOT(Other)) //
  76. cursor_adaptor(cursor_adaptor<Other> that)
  77. : toggle_(that.toggle_)
  78. , val_(std::move(that.val_))
  79. {}
  80. template<typename View>
  81. constexpr iterator_t<CRng> begin(View & view)
  82. {
  83. auto first = ranges::begin(view.base());
  84. toggle_ = first != ranges::end(view.base());
  85. return first;
  86. }
  87. constexpr range_value_t<Rng> read(iterator_t<CRng> const & it) const
  88. {
  89. return toggle_ ? *it : val_;
  90. }
  91. CPP_member
  92. constexpr auto equal(iterator_t<CRng> const & it0,
  93. iterator_t<CRng> const & it1,
  94. cursor_adaptor const & other) const //
  95. -> CPP_ret(bool)(
  96. requires sentinel_for<iterator_t<CRng>, iterator_t<CRng>>)
  97. {
  98. return it0 == it1 && toggle_ == other.toggle_;
  99. }
  100. constexpr void next(iterator_t<CRng> & it)
  101. {
  102. if(toggle_)
  103. ++it;
  104. toggle_ = !toggle_;
  105. }
  106. CPP_member
  107. constexpr auto prev(iterator_t<CRng> & it) //
  108. -> CPP_ret(void)(
  109. requires bidirectional_range<CRng>)
  110. {
  111. toggle_ = !toggle_;
  112. if(toggle_)
  113. --it;
  114. }
  115. CPP_member
  116. constexpr auto distance_to(iterator_t<CRng> const & it,
  117. iterator_t<CRng> const & other_it,
  118. cursor_adaptor const & other) const
  119. -> CPP_ret(range_difference_t<Rng>)(
  120. requires sized_sentinel_for<iterator_t<CRng>, iterator_t<CRng>>)
  121. {
  122. return (other_it - it) * 2 + (other.toggle_ - toggle_);
  123. }
  124. CPP_member
  125. constexpr auto advance(iterator_t<CRng> & it, range_difference_t<CRng> n) //
  126. -> CPP_ret(void)(
  127. requires random_access_range<CRng>)
  128. {
  129. ranges::advance(it, n >= 0 ? (n + toggle_) / 2 : (n - !toggle_) / 2);
  130. if(n % 2 != 0)
  131. toggle_ = !toggle_;
  132. }
  133. };
  134. template<bool Const>
  135. struct sentinel_adaptor : adaptor_base
  136. {
  137. private:
  138. using CRng = meta::const_if_c<Const, Rng>;
  139. public:
  140. sentinel_adaptor() = default;
  141. template(bool Other)(
  142. requires Const AND CPP_NOT(Other)) //
  143. sentinel_adaptor(sentinel_adaptor<Other>)
  144. {}
  145. static constexpr bool empty(iterator_t<CRng> const & it,
  146. cursor_adaptor<Const> const &,
  147. sentinel_t<CRng> const & sent)
  148. {
  149. return it == sent;
  150. }
  151. };
  152. constexpr cursor_adaptor<false> begin_adaptor()
  153. {
  154. return cursor_adaptor<false>{val_};
  155. }
  156. CPP_member
  157. constexpr auto begin_adaptor() const //
  158. -> CPP_ret(cursor_adaptor<true>)(
  159. requires range<Rng const>)
  160. {
  161. return cursor_adaptor<true>{val_};
  162. }
  163. CPP_member
  164. constexpr auto end_adaptor() //
  165. -> CPP_ret(cursor_adaptor<false>)(
  166. requires common_range<Rng> && (!single_pass_iterator_<iterator_t<Rng>>))
  167. {
  168. return cursor_adaptor<false>{val_};
  169. }
  170. CPP_member
  171. constexpr auto end_adaptor() noexcept //
  172. -> CPP_ret(sentinel_adaptor<false>)(
  173. requires (!common_range<Rng>) || single_pass_iterator_<iterator_t<Rng>>)
  174. {
  175. return {};
  176. }
  177. template(bool Const = true)(
  178. requires Const AND range<meta::const_if_c<Const, Rng>> AND
  179. common_range<meta::const_if_c<Const, Rng>> AND
  180. (!single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>)) //
  181. constexpr cursor_adaptor<Const> end_adaptor() const
  182. {
  183. return cursor_adaptor<true>{val_};
  184. }
  185. template(bool Const = true)(
  186. requires Const AND range<meta::const_if_c<Const, Rng>> AND
  187. (!common_range<meta::const_if_c<Const, Rng>> ||
  188. single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>)) //
  189. constexpr sentinel_adaptor<Const> end_adaptor() const noexcept
  190. {
  191. return {};
  192. }
  193. range_value_t<Rng> val_;
  194. };
  195. template<typename Rng>
  196. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<intersperse_view<Rng>> = //
  197. enable_borrowed_range<Rng>;
  198. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  199. template<typename Rng>
  200. intersperse_view(Rng &&, range_value_t<Rng>)
  201. -> intersperse_view<views::all_t<Rng>>;
  202. #endif
  203. namespace views
  204. {
  205. struct intersperse_base_fn
  206. {
  207. template(typename Rng)(
  208. requires viewable_range<Rng> AND input_range<Rng> AND
  209. convertible_to<range_reference_t<Rng>, range_value_t<Rng>> AND
  210. semiregular<range_value_t<Rng>>)
  211. constexpr intersperse_view<all_t<Rng>> //
  212. operator()(Rng && rng, range_value_t<Rng> val) const
  213. {
  214. return {all(static_cast<Rng &&>(rng)), std::move(val)};
  215. }
  216. };
  217. struct intersperse_fn : intersperse_base_fn
  218. {
  219. using intersperse_base_fn::operator();
  220. template(typename T)(
  221. requires copyable<T>)
  222. constexpr auto operator()(T t) const
  223. {
  224. return make_view_closure(bind_back(intersperse_base_fn{}, std::move(t)));
  225. }
  226. };
  227. /// \relates intersperse_fn
  228. /// \ingroup group-views
  229. RANGES_INLINE_VARIABLE(intersperse_fn, intersperse)
  230. } // namespace views
  231. } // namespace ranges
  232. #include <range/v3/detail/epilogue.hpp>
  233. #include <range/v3/detail/satisfy_boost_range.hpp>
  234. RANGES_SATISFY_BOOST_RANGE(::ranges::intersperse_view)
  235. #endif