sliding.hpp 12 KB

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