slice.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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_SLICE_HPP
  14. #define RANGES_V3_VIEW_SLICE_HPP
  15. #include <type_traits>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/functional/bind_back.hpp>
  19. #include <range/v3/iterator/counted_iterator.hpp>
  20. #include <range/v3/iterator/default_sentinel.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/iterator/traits.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/all.hpp>
  28. #include <range/v3/view/drop_exactly.hpp>
  29. #include <range/v3/view/facade.hpp>
  30. #include <range/v3/view/subrange.hpp>
  31. #include <range/v3/view/view.hpp>
  32. #include <range/v3/detail/prologue.hpp>
  33. namespace ranges
  34. {
  35. /// \cond
  36. namespace detail
  37. {
  38. template<typename Rng, typename Int>
  39. iterator_t<Rng> pos_at_(Rng && rng, Int i, input_range_tag, std::true_type)
  40. {
  41. RANGES_EXPECT(0 <= i);
  42. return next(ranges::begin(rng), i);
  43. }
  44. template<typename Rng, typename Int>
  45. iterator_t<Rng> pos_at_(Rng && rng, Int i, bidirectional_range_tag,
  46. std::false_type)
  47. {
  48. if(0 > i)
  49. {
  50. // If it's not common and we know the size, faster to count from the front
  51. if(RANGES_CONSTEXPR_IF(sized_range<Rng> && !common_range<Rng>))
  52. return next(ranges::begin(rng), distance(rng) + i);
  53. // Otherwise, probably faster to count from the back.
  54. return next(ranges::next(ranges::begin(rng), ranges::end(rng)), i);
  55. }
  56. return next(ranges::begin(rng), i);
  57. }
  58. template<typename Rng, typename Int>
  59. iterator_t<Rng> pos_at_(Rng && rng, Int i, input_range_tag, std::false_type)
  60. {
  61. RANGES_EXPECT(i >= 0 || (bool)sized_range<Rng> || (bool)forward_range<Rng>);
  62. if(0 > i)
  63. return next(ranges::begin(rng), distance(rng) + i);
  64. return next(ranges::begin(rng), i);
  65. }
  66. template<typename Rng, bool IsRandomAccess>
  67. struct slice_view_ : view_facade<slice_view<Rng>, finite>
  68. {
  69. private:
  70. friend range_access;
  71. Rng rng_;
  72. range_difference_t<Rng> from_, count_;
  73. detail::non_propagating_cache<iterator_t<Rng>> begin_;
  74. iterator_t<Rng> get_begin_()
  75. {
  76. if(!begin_)
  77. begin_ = detail::pos_at_(
  78. rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
  79. return *begin_;
  80. }
  81. public:
  82. slice_view_() = default;
  83. constexpr slice_view_(Rng rng, range_difference_t<Rng> from,
  84. range_difference_t<Rng> count)
  85. : rng_(std::move(rng))
  86. , from_(from)
  87. , count_(count)
  88. {}
  89. counted_iterator<iterator_t<Rng>> begin()
  90. {
  91. return make_counted_iterator(get_begin_(), count_);
  92. }
  93. default_sentinel_t end()
  94. {
  95. return {};
  96. }
  97. auto size() const
  98. {
  99. return static_cast<detail::iter_size_t<iterator_t<Rng>>>(count_);
  100. }
  101. Rng base() const
  102. {
  103. return rng_;
  104. }
  105. };
  106. template<typename Rng>
  107. struct slice_view_<Rng, true> : view_interface<slice_view<Rng>, finite>
  108. {
  109. private:
  110. Rng rng_;
  111. range_difference_t<Rng> from_, count_;
  112. public:
  113. slice_view_() = default;
  114. constexpr slice_view_(Rng rng, range_difference_t<Rng> from,
  115. range_difference_t<Rng> count)
  116. : rng_(std::move(rng))
  117. , from_(from)
  118. , count_(count)
  119. {
  120. RANGES_EXPECT(0 <= count_);
  121. }
  122. iterator_t<Rng> begin()
  123. {
  124. return detail::pos_at_(
  125. rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
  126. }
  127. iterator_t<Rng> end()
  128. {
  129. return detail::pos_at_(
  130. rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{}) +
  131. count_;
  132. }
  133. template(typename BaseRng = Rng)(
  134. requires range<BaseRng const>)
  135. iterator_t<BaseRng const> begin() const
  136. {
  137. return detail::pos_at_(
  138. rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
  139. }
  140. template(typename BaseRng = Rng)(
  141. requires range<BaseRng const>)
  142. iterator_t<BaseRng const> end() const
  143. {
  144. return detail::pos_at_(
  145. rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{}) +
  146. count_;
  147. }
  148. auto size() const
  149. {
  150. return static_cast<detail::iter_size_t<iterator_t<Rng>>>(count_);
  151. }
  152. Rng base() const
  153. {
  154. return rng_;
  155. }
  156. };
  157. } // namespace detail
  158. /// \endcond
  159. /// \addtogroup group-views
  160. /// @{
  161. template<typename Rng>
  162. struct slice_view : detail::slice_view_<Rng, (bool)random_access_range<Rng>>
  163. {
  164. using detail::slice_view_<Rng, (bool)random_access_range<Rng>>::slice_view_;
  165. };
  166. template<typename Rng>
  167. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<slice_view<Rng>> = //
  168. enable_borrowed_range<Rng>;
  169. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  170. template<typename Rng>
  171. slice_view(Rng &&, range_difference_t<Rng>, range_difference_t<Rng>)
  172. ->slice_view<views::all_t<Rng>>;
  173. #endif
  174. namespace views
  175. {
  176. struct slice_base_fn
  177. {
  178. private:
  179. template<typename Rng>
  180. static constexpr slice_view<all_t<Rng>> impl_(Rng && rng,
  181. range_difference_t<Rng> from,
  182. range_difference_t<Rng> count,
  183. input_range_tag, range_tag = {})
  184. {
  185. return {all(static_cast<Rng &&>(rng)), from, count};
  186. }
  187. template(typename Rng)(
  188. requires borrowed_range<Rng>)
  189. static subrange<iterator_t<Rng>> impl_(Rng && rng,
  190. range_difference_t<Rng> from,
  191. range_difference_t<Rng> count,
  192. random_access_range_tag,
  193. common_range_tag = {})
  194. {
  195. auto it =
  196. detail::pos_at_(rng, from, range_tag_of<Rng>{}, is_infinite<Rng>{});
  197. return {it, it + count};
  198. }
  199. public:
  200. // slice(rng, 2, 4)
  201. template(typename Rng)(
  202. requires viewable_range<Rng> AND input_range<Rng>)
  203. constexpr auto operator()(Rng && rng,
  204. range_difference_t<Rng> from,
  205. range_difference_t<Rng> to) const
  206. {
  207. RANGES_EXPECT(0 <= from && from <= to);
  208. return slice_base_fn::impl_(
  209. static_cast<Rng &&>(rng), from, to - from, range_tag_of<Rng>{});
  210. }
  211. // slice(rng, 4, end-2)
  212. // TODO Support Forward, non-Sized ranges by returning a range that
  213. // doesn't know it's size?
  214. template(typename Rng)(
  215. requires viewable_range<Rng> AND input_range<Rng> AND sized_range<Rng>)
  216. auto operator()(Rng && rng,
  217. range_difference_t<Rng> from,
  218. detail::from_end_of_t<Rng> to) const
  219. {
  220. static_assert(!is_infinite<Rng>::value,
  221. "Can't index from the end of an infinite range!");
  222. RANGES_EXPECT(0 <= from);
  223. RANGES_ASSERT(from <= distance(rng) + to.dist_);
  224. return slice_base_fn::impl_(static_cast<Rng &&>(rng),
  225. from,
  226. distance(rng) + to.dist_ - from,
  227. range_tag_of<Rng>{});
  228. }
  229. // slice(rng, end-4, end-2)
  230. template(typename Rng)(
  231. requires viewable_range<Rng> AND
  232. (forward_range<Rng> || (input_range<Rng> && sized_range<Rng>)))
  233. auto operator()(Rng && rng,
  234. detail::from_end_of_t<Rng> from,
  235. detail::from_end_of_t<Rng> to) const
  236. {
  237. static_assert(!is_infinite<Rng>::value,
  238. "Can't index from the end of an infinite range!");
  239. RANGES_EXPECT(from.dist_ <= to.dist_);
  240. return slice_base_fn::impl_(static_cast<Rng &&>(rng),
  241. from.dist_,
  242. to.dist_ - from.dist_,
  243. range_tag_of<Rng>{},
  244. common_range_tag_of<Rng>{});
  245. }
  246. // slice(rng, 4, end)
  247. template(typename Rng)(
  248. requires viewable_range<Rng> AND input_range<Rng>)
  249. auto operator()(Rng && rng, range_difference_t<Rng> from, end_fn) const
  250. {
  251. RANGES_EXPECT(0 <= from);
  252. return ranges::views::drop_exactly(static_cast<Rng &&>(rng), from);
  253. }
  254. // slice(rng, end-4, end)
  255. template(typename Rng)(
  256. requires viewable_range<Rng> AND
  257. (forward_range<Rng> || (input_range<Rng> && sized_range<Rng>)))
  258. auto operator()(Rng && rng,
  259. detail::from_end_of_t<Rng> from,
  260. end_fn) const
  261. {
  262. static_assert(!is_infinite<Rng>::value,
  263. "Can't index from the end of an infinite range!");
  264. return slice_base_fn::impl_(static_cast<Rng &&>(rng),
  265. from.dist_,
  266. -from.dist_,
  267. range_tag_of<Rng>{},
  268. common_range_tag_of<Rng>{});
  269. }
  270. };
  271. struct slice_fn : slice_base_fn
  272. {
  273. using slice_base_fn::operator();
  274. // Overloads for the pipe syntax: rng | views::slice(from,to)
  275. template(typename Int)(
  276. requires detail::integer_like_<Int>)
  277. constexpr auto operator()(Int from, Int to) const
  278. {
  279. return make_view_closure(bind_back(slice_base_fn{}, from, to));
  280. }
  281. template(typename Int)(
  282. requires detail::integer_like_<Int>)
  283. constexpr auto operator()(Int from, detail::from_end_<Int> to) const
  284. {
  285. return make_view_closure(bind_back(slice_base_fn{}, from, to));
  286. }
  287. template(typename Int)(
  288. requires detail::integer_like_<Int>)
  289. constexpr auto operator()(detail::from_end_<Int> from,
  290. detail::from_end_<Int> to) const
  291. {
  292. return make_view_closure(bind_back(slice_base_fn{}, from, to));
  293. }
  294. template(typename Int)(
  295. requires detail::integer_like_<Int>)
  296. constexpr auto operator()(Int from, end_fn) const
  297. {
  298. return make_view_closure(
  299. bind_back(ranges::views::drop_exactly_base_fn{}, from));
  300. }
  301. template(typename Int)(
  302. requires detail::integer_like_<Int>)
  303. constexpr auto operator()(detail::from_end_<Int> from, end_fn to) const
  304. {
  305. return make_view_closure(bind_back(slice_base_fn{}, from, to));
  306. }
  307. };
  308. /// \relates _slice_fn
  309. /// \ingroup group-views
  310. RANGES_INLINE_VARIABLE(slice_fn, slice)
  311. } // namespace views
  312. /// @}
  313. } // namespace ranges
  314. #include <range/v3/detail/epilogue.hpp>
  315. #include <range/v3/detail/satisfy_boost_range.hpp>
  316. RANGES_SATISFY_BOOST_RANGE(::ranges::slice_view)
  317. #endif