You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sliding.hpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. // Copyright Tobias Mayer 2016
  6. // Copyright Casey Carter 2016
  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_SLIDING_HPP
  16. #define RANGES_V3_VIEW_SLIDING_HPP
  17. #include <utility>
  18. #include <meta/meta.hpp>
  19. #include <range/v3/range_fwd.hpp>
  20. #include <range/v3/functional/bind_back.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/range/access.hpp>
  23. #include <range/v3/range/concepts.hpp>
  24. #include <range/v3/range/traits.hpp>
  25. #include <range/v3/utility/optional.hpp>
  26. #include <range/v3/utility/static_const.hpp>
  27. #include <range/v3/view/adaptor.hpp>
  28. #include <range/v3/view/all.hpp>
  29. #include <range/v3/view/counted.hpp>
  30. #include <range/v3/view/view.hpp>
  31. namespace ranges
  32. {
  33. /// \cond
  34. namespace sliding_view_detail
  35. {
  36. enum class cache
  37. {
  38. none,
  39. first,
  40. last
  41. };
  42. template<typename Rng>
  43. using caching = std::integral_constant<
  44. cache, random_access_range<Rng> && sized_range<Rng>
  45. ? cache::none
  46. : bidirectional_range<Rng> && common_range<Rng> ? cache::last
  47. : cache::first>;
  48. } // namespace sliding_view_detail
  49. /// \endcond
  50. template<typename Rng,
  51. sliding_view_detail::cache = sliding_view_detail::caching<Rng>::value>
  52. struct sliding_view;
  53. /// \cond
  54. namespace sliding_view_detail
  55. {
  56. template<typename Rng>
  57. using uncounted_t =
  58. decltype(ranges::uncounted(std::declval<iterator_t<Rng> &>()));
  59. template<typename Rng, bool = (bool)random_access_range<Rng>>
  60. struct trailing
  61. {
  62. trailing() = default;
  63. constexpr trailing(Rng & rng)
  64. : it_{uncounted(ranges::begin(rng))}
  65. {}
  66. constexpr uncounted_t<Rng> get(iterator_t<Rng> const &,
  67. range_difference_t<Rng>) const
  68. {
  69. return it_;
  70. }
  71. void next()
  72. {
  73. ++it_;
  74. }
  75. CPP_member
  76. auto prev() -> CPP_ret(void)(requires bidirectional_range<Rng>)
  77. {
  78. --it_;
  79. }
  80. private:
  81. uncounted_t<Rng> it_;
  82. };
  83. template<typename Rng>
  84. struct trailing<Rng, true>
  85. {
  86. trailing() = default;
  87. constexpr trailing(Rng &) noexcept
  88. {}
  89. constexpr uncounted_t<Rng> get(iterator_t<Rng> const & it,
  90. range_difference_t<Rng> n) const
  91. {
  92. return uncounted(it - (n - 1));
  93. }
  94. void next()
  95. {}
  96. void prev()
  97. {}
  98. };
  99. template<typename Rng>
  100. struct RANGES_EMPTY_BASES sv_base
  101. : view_adaptor<sliding_view<Rng>, Rng,
  102. is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
  103. , private detail::non_propagating_cache<iterator_t<Rng>, sv_base<Rng>,
  104. caching<Rng>::value != cache::none>
  105. {
  106. CPP_assert(forward_range<Rng>);
  107. sv_base() = default;
  108. sv_base(Rng rng, range_difference_t<Rng> n)
  109. : sv_base::view_adaptor(std::move(rng))
  110. , n_(n)
  111. {
  112. RANGES_ASSERT(0 < n_);
  113. }
  114. CPP_member
  115. auto CPP_fun(size)()(const requires sized_range<Rng const>)
  116. {
  117. auto const count = ranges::size(this->base());
  118. auto const n = static_cast<range_size_t<Rng const>>(n_);
  119. return count < n ? 0 : count - n + 1;
  120. }
  121. CPP_member
  122. auto CPP_fun(size)()(requires sized_range<Rng>)
  123. {
  124. auto const count = ranges::size(this->base());
  125. auto const n = static_cast<range_size_t<Rng>>(n_);
  126. return count < n ? 0 : count - n + 1;
  127. }
  128. protected:
  129. range_difference_t<Rng> n_;
  130. optional<iterator_t<Rng>> & cache() &
  131. {
  132. return static_cast<cache_t &>(*this);
  133. }
  134. optional<iterator_t<Rng>> const & cache() const &
  135. {
  136. return static_cast<cache_t const &>(*this);
  137. }
  138. private:
  139. using cache_t = detail::non_propagating_cache<iterator_t<Rng>, sv_base<Rng>>;
  140. };
  141. } // namespace sliding_view_detail
  142. /// \endcond
  143. /// \addtogroup group-views
  144. /// @{
  145. template<typename Rng>
  146. struct sliding_view<Rng, sliding_view_detail::cache::first>
  147. : sliding_view_detail::sv_base<Rng>
  148. {
  149. private:
  150. friend range_access;
  151. iterator_t<Rng> get_first()
  152. {
  153. auto & first = this->cache();
  154. if(!first)
  155. {
  156. first = ranges::next(
  157. ranges::begin(this->base()), this->n_ - 1, ranges::end(this->base()));
  158. }
  159. return *first;
  160. }
  161. struct RANGES_EMPTY_BASES adaptor
  162. : adaptor_base
  163. , sliding_view_detail::trailing<Rng>
  164. {
  165. private:
  166. using base_t = sliding_view_detail::trailing<Rng>;
  167. range_difference_t<Rng> n_ = {};
  168. public:
  169. adaptor() = default;
  170. adaptor(sliding_view * v)
  171. : base_t{v->base()}
  172. , n_{v->n_}
  173. {}
  174. iterator_t<Rng> begin(sliding_view & v)
  175. {
  176. return v.get_first();
  177. }
  178. auto read(iterator_t<Rng> const & it) const
  179. -> decltype(views::counted(uncounted(it), n_))
  180. {
  181. return views::counted(base_t::get(it, n_), n_);
  182. }
  183. void next(iterator_t<Rng> & it)
  184. {
  185. ++it;
  186. base_t::next();
  187. }
  188. CPP_member
  189. auto prev(iterator_t<Rng> & it) -> CPP_ret(void)( //
  190. requires bidirectional_range<Rng>)
  191. {
  192. base_t::prev();
  193. --it;
  194. }
  195. CPP_member
  196. auto advance(iterator_t<Rng> & it, range_difference_t<Rng> n)
  197. -> CPP_ret(void)( //
  198. requires random_access_range<Rng>)
  199. {
  200. it += n;
  201. }
  202. };
  203. adaptor begin_adaptor()
  204. {
  205. return {this};
  206. }
  207. meta::if_c<common_range<Rng>, adaptor, adaptor_base> end_adaptor()
  208. {
  209. return {this};
  210. }
  211. public:
  212. using sliding_view::sv_base::sv_base;
  213. };
  214. template<typename Rng>
  215. struct sliding_view<Rng, sliding_view_detail::cache::last>
  216. : sliding_view_detail::sv_base<Rng>
  217. {
  218. private:
  219. friend range_access;
  220. iterator_t<Rng> get_last()
  221. {
  222. auto & last = this->cache();
  223. if(!last)
  224. {
  225. last = ranges::prev(
  226. ranges::end(this->base()), this->n_ - 1, ranges::begin(this->base()));
  227. }
  228. return *last;
  229. }
  230. struct adaptor : adaptor_base
  231. {
  232. private:
  233. range_difference_t<Rng> n_ = {};
  234. public:
  235. adaptor() = default;
  236. adaptor(sliding_view * v)
  237. : n_{v->n_}
  238. {}
  239. iterator_t<Rng> end(sliding_view & v)
  240. {
  241. return v.get_last();
  242. }
  243. auto read(iterator_t<Rng> const & it) const
  244. -> decltype(views::counted(uncounted(it), n_))
  245. {
  246. return views::counted(uncounted(it), n_);
  247. }
  248. };
  249. adaptor begin_adaptor()
  250. {
  251. return {this};
  252. }
  253. adaptor end_adaptor()
  254. {
  255. return {this};
  256. }
  257. public:
  258. using sliding_view::sv_base::sv_base;
  259. };
  260. template<typename Rng>
  261. struct sliding_view<Rng, sliding_view_detail::cache::none>
  262. : sliding_view_detail::sv_base<Rng>
  263. {
  264. private:
  265. friend range_access;
  266. template<bool Const>
  267. struct adaptor : adaptor_base
  268. {
  269. private:
  270. friend adaptor<!Const>;
  271. using CRng = meta::const_if_c<Const, Rng>;
  272. range_difference_t<Rng> n_ = 0;
  273. public:
  274. adaptor() = default;
  275. adaptor(range_difference_t<Rng> n)
  276. : n_(n)
  277. {}
  278. template<bool Other>
  279. CPP_ctor(adaptor)(adaptor<Other> that)( //
  280. requires Const && (!Other))
  281. : n_(that.n_)
  282. {}
  283. iterator_t<CRng> end(meta::const_if_c<Const, sliding_view> & v) const
  284. {
  285. auto const sz = ranges::distance(v.base());
  286. auto const offset = n_ - 1 < sz ? n_ - 1 : sz;
  287. return ranges::begin(v.base()) + (sz - offset);
  288. }
  289. auto read(iterator_t<CRng> const & it) const
  290. -> decltype(views::counted(uncounted(it), n_))
  291. {
  292. return views::counted(uncounted(it), n_);
  293. }
  294. };
  295. adaptor<simple_view<Rng>()> begin_adaptor()
  296. {
  297. return {this->n_};
  298. }
  299. CPP_member
  300. auto begin_adaptor() const -> CPP_ret(adaptor<true>)( //
  301. requires range<Rng const>)
  302. {
  303. return {this->n_};
  304. }
  305. adaptor<simple_view<Rng>()> end_adaptor()
  306. {
  307. return {this->n_};
  308. }
  309. CPP_member
  310. auto end_adaptor() const -> CPP_ret(adaptor<true>)( //
  311. requires range<Rng const>)
  312. {
  313. return {this->n_};
  314. }
  315. public:
  316. using sliding_view::sv_base::sv_base;
  317. };
  318. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  319. template<typename Rng>
  320. sliding_view(Rng &&, range_difference_t<Rng>)->sliding_view<views::all_t<Rng>>;
  321. #endif
  322. namespace views
  323. {
  324. // In: range<T>
  325. // Out: range<range<T>>, where each inner range has $n$ elements.
  326. struct sliding_fn
  327. {
  328. private:
  329. friend view_access;
  330. template<typename Int>
  331. static constexpr auto CPP_fun(bind)(sliding_fn sliding, Int n)( //
  332. requires integral<Int>)
  333. {
  334. return make_pipeable(bind_back(sliding, n));
  335. }
  336. public:
  337. template<typename Rng>
  338. constexpr auto operator()(Rng && rng, range_difference_t<Rng> n) const
  339. -> CPP_ret(sliding_view<all_t<Rng>>)( //
  340. requires viewable_range<Rng> && forward_range<Rng>)
  341. {
  342. return {all(static_cast<Rng &&>(rng)), n};
  343. }
  344. };
  345. /// \relates sliding_fn
  346. /// \ingroup group-views
  347. RANGES_INLINE_VARIABLE(view<sliding_fn>, sliding)
  348. } // namespace views
  349. /// @}
  350. } // namespace ranges
  351. #endif