subrange.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. // Copyright Casey Carter 2017
  6. //
  7. // Use, modification and distribution is subject to the
  8. // Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. // Project home: https://github.com/ericniebler/range-v3
  13. //
  14. #ifndef RANGES_V3_VIEW_SUBRANGE_HPP
  15. #define RANGES_V3_VIEW_SUBRANGE_HPP
  16. #include <tuple>
  17. #include <type_traits>
  18. #include <utility>
  19. #include <meta/meta.hpp>
  20. #include <concepts/concepts.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/dangling.hpp>
  26. #include <range/v3/utility/get.hpp>
  27. #include <range/v3/view/interface.hpp>
  28. #include <range/v3/detail/prologue.hpp>
  29. namespace ranges
  30. {
  31. /// \addtogroup group-views
  32. /// @{
  33. enum class subrange_kind : bool
  34. {
  35. unsized,
  36. sized
  37. };
  38. /// \cond
  39. namespace detail
  40. {
  41. // clang-format off
  42. /// \concept convertible_to_not_slicing_
  43. /// \brief The \c convertible_to_not_slicing_ concept
  44. template<typename From, typename To>
  45. CPP_concept convertible_to_not_slicing_ =
  46. convertible_to<From, To> &&
  47. // A conversion is a slicing conversion if the source and the destination
  48. // are both pointers, and if the pointed-to types differ after removing
  49. // cv qualifiers.
  50. (!(std::is_pointer<decay_t<From>>::value &&
  51. std::is_pointer<decay_t<To>>::value &&
  52. not_same_as_<std::remove_pointer_t<decay_t<From>>,
  53. std::remove_pointer_t<decay_t<To>>>));
  54. template<std::size_t N, typename T>
  55. using tuple_element_fun_t = void (*)(meta::_t<std::tuple_element<N, T>> const &);
  56. /// \concept pair_like_impl_
  57. /// \brief The \c pair_like_impl_ concept
  58. template<typename T>
  59. CPP_requires(pair_like_impl_, //
  60. requires(T t, tuple_element_fun_t<0, T> p0, tuple_element_fun_t<1, T> p1) //
  61. (
  62. p0( get<0>(t) ),
  63. p1( get<1>(t) )
  64. ));
  65. /// \concept pair_like_impl_
  66. /// \brief The \c pair_like_impl_ concept
  67. template<typename T>
  68. CPP_concept pair_like_impl_ = CPP_requires_ref(detail::pair_like_impl_, T);
  69. /// \concept is_complete_
  70. /// \brief The \c is_complete_ concept
  71. template(typename T)(
  72. concept (is_complete_)(T),
  73. 0 != sizeof(T));
  74. /// \concept is_complete_
  75. /// \brief The \c is_complete_ concept
  76. template<typename T>
  77. CPP_concept is_complete_ = //
  78. CPP_concept_ref(is_complete_, T);
  79. template(typename T)( //
  80. concept (pair_like_)(T), //
  81. is_complete_<std::tuple_size<T>> AND
  82. derived_from<std::tuple_size<T>, meta::size_t<2>> AND
  83. detail::pair_like_impl_<T>);
  84. /// \concept pair_like
  85. /// \brief The \c pair_like concept
  86. template<typename T>
  87. CPP_concept pair_like = //
  88. CPP_concept_ref(detail::pair_like_, T);
  89. // clang-format off
  90. template(typename T, typename U, typename V)( //
  91. concept (pair_like_convertible_from_helper_)(T, U, V), //
  92. convertible_to_not_slicing_<U, meta::_t<std::tuple_element<0, T>>> AND
  93. convertible_to<V, meta::_t<std::tuple_element<1, T>>>);
  94. /// \concept pair_like_convertible_from_helper_
  95. /// \brief The \c pair_like_convertible_from_helper_ concept
  96. template<typename T, typename U, typename V>
  97. CPP_concept pair_like_convertible_from_helper_ = //
  98. CPP_concept_ref(pair_like_convertible_from_helper_, T, U, V);
  99. template(typename T, typename U, typename V)( //
  100. concept (pair_like_convertible_from_impl_)(T, U, V),
  101. (!range<T>) AND
  102. constructible_from<T, U, V> AND
  103. pair_like<uncvref_t<T>> AND
  104. pair_like_convertible_from_helper_<T, U, V>);
  105. /// \concept pair_like_convertible_from_
  106. /// \brief The \c pair_like_convertible_from_ concept
  107. template<typename T, typename U, typename V>
  108. CPP_concept pair_like_convertible_from_ =
  109. CPP_concept_ref(detail::pair_like_convertible_from_impl_, T, U, V);
  110. /// \concept range_convertible_to_impl_
  111. /// \brief The \c range_convertible_to_impl_ concept
  112. template(typename R, typename I, typename S)(
  113. concept (range_convertible_to_impl_)(R, I, S),
  114. convertible_to_not_slicing_<iterator_t<R>, I> AND
  115. convertible_to<sentinel_t<R>, S>);
  116. /// \concept range_convertible_to_
  117. /// \brief The \c range_convertible_to_ concept
  118. template<typename R, typename I, typename S>
  119. CPP_concept range_convertible_to_ =
  120. borrowed_range<R> &&
  121. CPP_concept_ref(detail::range_convertible_to_impl_, R, I, S);
  122. // clang-format on
  123. template(typename S, typename I)(
  124. requires sentinel_for<S, I>)
  125. constexpr bool is_sized_sentinel_() noexcept
  126. {
  127. return (bool)sized_sentinel_for<S, I>;
  128. }
  129. template<subrange_kind K, typename S, typename I>
  130. constexpr bool store_size_() noexcept
  131. {
  132. return K == subrange_kind::sized && !(bool)sized_sentinel_for<S, I>;
  133. }
  134. } // namespace detail
  135. /// \endcond
  136. template< //
  137. typename I, //
  138. typename S = I, //
  139. subrange_kind K = static_cast<subrange_kind>(detail::is_sized_sentinel_<S, I>())>
  140. struct subrange;
  141. template<typename I, typename S, subrange_kind K>
  142. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
  143. /// \cond
  144. namespace _subrange_
  145. {
  146. struct adl_hook
  147. {};
  148. template(std::size_t N, typename I, typename S, subrange_kind K)(
  149. requires (N == 0)) //
  150. constexpr I get(subrange<I, S, K> const & r)
  151. {
  152. return r.begin();
  153. }
  154. template(std::size_t N, typename I, typename S, subrange_kind K)(
  155. requires (N == 1)) //
  156. constexpr S get(subrange<I, S, K> const & r)
  157. {
  158. return r.end();
  159. }
  160. } // namespace _subrange_
  161. /// \endcond
  162. template<typename I, typename S, subrange_kind K>
  163. struct subrange
  164. : view_interface<subrange<I, S, K>,
  165. same_as<S, unreachable_sentinel_t>
  166. ? infinite
  167. : K == subrange_kind::sized ? finite : unknown>
  168. , private _subrange_::adl_hook
  169. {
  170. CPP_assert(input_or_output_iterator<I>);
  171. CPP_assert(sentinel_for<S, I>);
  172. CPP_assert(K == subrange_kind::sized || !sized_sentinel_for<S, I>);
  173. CPP_assert(K != subrange_kind::sized || !same_as<S, unreachable_sentinel_t>);
  174. using size_type = detail::iter_size_t<I>;
  175. using iterator = I;
  176. using sentinel = S;
  177. subrange() = default;
  178. template(typename I2)(
  179. requires detail::convertible_to_not_slicing_<I2, I> AND
  180. (!detail::store_size_<K, S, I>())) //
  181. constexpr subrange(I2 && i, S s)
  182. : data_{static_cast<I2 &&>(i), std::move(s)}
  183. {}
  184. template(typename I2)(
  185. requires detail::convertible_to_not_slicing_<I2, I> AND
  186. (detail::store_size_<K, S, I>())) //
  187. constexpr subrange(I2 && i, S s, size_type n)
  188. : data_{static_cast<I2 &&>(i), std::move(s), n}
  189. {
  190. if(RANGES_CONSTEXPR_IF((bool)random_access_iterator<I>))
  191. {
  192. using D = iter_difference_t<I>;
  193. RANGES_EXPECT(n <= (size_type)std::numeric_limits<D>::max());
  194. RANGES_EXPECT(ranges::next(first_(), (D)n) == last_());
  195. }
  196. }
  197. template(typename I2)(
  198. requires detail::convertible_to_not_slicing_<I2, I> AND
  199. sized_sentinel_for<S, I>)
  200. constexpr subrange(I2 && i, S s, size_type n)
  201. : data_{static_cast<I2 &&>(i), std::move(s)}
  202. {
  203. RANGES_EXPECT(static_cast<size_type>(last_() - first_()) == n);
  204. }
  205. template(typename R)(
  206. requires (!same_as<detail::decay_t<R>, subrange>) AND
  207. detail::range_convertible_to_<R, I, S> AND
  208. (!detail::store_size_<K, S, I>()))
  209. constexpr subrange(R && r)
  210. : subrange{ranges::begin(r), ranges::end(r)}
  211. {}
  212. template(typename R)(
  213. requires (!same_as<detail::decay_t<R>, subrange>) AND
  214. detail::range_convertible_to_<R, I, S> AND
  215. (detail::store_size_<K, S, I>()) AND
  216. sized_range<R>)
  217. constexpr subrange(R && r)
  218. : subrange{ranges::begin(r), ranges::end(r), ranges::size(r)}
  219. {}
  220. template(typename R)(
  221. requires (K == subrange_kind::sized) AND
  222. detail::range_convertible_to_<R, I, S>)
  223. constexpr subrange(R && r, size_type n) //
  224. : subrange{ranges::begin(r), ranges::end(r), n}
  225. {
  226. if(RANGES_CONSTEXPR_IF((bool)sized_range<R>))
  227. {
  228. RANGES_EXPECT(n == ranges::size(r));
  229. }
  230. }
  231. template(typename PairLike)(
  232. requires (!same_as<PairLike, subrange>) AND
  233. detail::pair_like_convertible_from_<PairLike, I const &, S const &>)
  234. constexpr operator PairLike() const
  235. {
  236. return PairLike(first_(), last_());
  237. }
  238. constexpr I begin() const noexcept(std::is_nothrow_copy_constructible<I>::value)
  239. {
  240. return first_();
  241. }
  242. constexpr S end() const noexcept(std::is_nothrow_copy_constructible<S>::value)
  243. {
  244. return last_();
  245. }
  246. constexpr bool empty() const
  247. {
  248. return first_() == last_();
  249. }
  250. CPP_member
  251. constexpr auto size() const //
  252. -> CPP_ret(size_type)(
  253. requires (K == subrange_kind::sized))
  254. {
  255. return get_size_();
  256. }
  257. RANGES_NODISCARD
  258. constexpr subrange next(iter_difference_t<I> n = 1) const
  259. {
  260. auto tmp = *this;
  261. tmp.advance(n);
  262. return tmp;
  263. }
  264. CPP_member
  265. RANGES_NODISCARD constexpr auto prev(iter_difference_t<I> n = 1) const
  266. -> CPP_ret(subrange)(
  267. requires bidirectional_iterator<I>)
  268. {
  269. auto tmp = *this;
  270. tmp.advance(-n);
  271. return tmp;
  272. }
  273. constexpr subrange & advance(iter_difference_t<I> n)
  274. {
  275. set_size_(get_size_() -
  276. static_cast<size_type>(n - ranges::advance(first_(), n, last_())));
  277. return *this;
  278. }
  279. private:
  280. using data_t =
  281. meta::conditional_t< //
  282. detail::store_size_<K, S, I>(), //
  283. std::tuple<I, S, size_type>, //
  284. std::tuple<I, S>>;
  285. data_t data_;
  286. constexpr I & first_() noexcept
  287. {
  288. return std::get<0>(data_);
  289. }
  290. constexpr const I & first_() const noexcept
  291. {
  292. return std::get<0>(data_);
  293. }
  294. constexpr S & last_() noexcept
  295. {
  296. return std::get<1>(data_);
  297. }
  298. constexpr const S & last_() const noexcept
  299. {
  300. return std::get<1>(data_);
  301. }
  302. CPP_member
  303. constexpr auto get_size_() const //
  304. -> CPP_ret(size_type)(
  305. requires sized_sentinel_for<S, I>)
  306. {
  307. return static_cast<size_type>(last_() - first_());
  308. }
  309. CPP_member
  310. constexpr auto get_size_() const noexcept //
  311. -> CPP_ret(size_type)(
  312. requires (detail::store_size_<K, S, I>()))
  313. {
  314. return std::get<2>(data_);
  315. }
  316. static constexpr void set_size_(...) noexcept
  317. {}
  318. CPP_member
  319. constexpr auto set_size_(size_type n) noexcept //
  320. -> CPP_ret(void)(
  321. requires (detail::store_size_<K, S, I>()))
  322. {
  323. std::get<2>(data_) = n;
  324. }
  325. };
  326. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  327. template<typename I, typename S>
  328. subrange(I, S) //
  329. -> subrange<I, S>;
  330. template(typename I, typename S)(
  331. requires input_or_output_iterator<I> AND sentinel_for<S, I>)
  332. subrange(I, S, detail::iter_size_t<I>)
  333. -> subrange<I, S, subrange_kind::sized>;
  334. template(typename R)(
  335. requires borrowed_range<R>)
  336. subrange(R &&) //
  337. -> subrange<iterator_t<R>, sentinel_t<R>,
  338. (sized_range<R> ||
  339. sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
  340. ? subrange_kind::sized
  341. : subrange_kind::unsized>;
  342. template(typename R)(
  343. requires borrowed_range<R>)
  344. subrange(R &&, detail::iter_size_t<iterator_t<R>>)
  345. -> subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
  346. #endif
  347. // in lieu of deduction guides, use make_subrange
  348. struct make_subrange_fn
  349. {
  350. template<typename I, typename S>
  351. constexpr subrange<I, S> operator()(I i, S s) const
  352. {
  353. return {i, s};
  354. }
  355. template(typename I, typename S)(
  356. requires input_or_output_iterator<I> AND sentinel_for<S, I>)
  357. constexpr subrange<I, S, subrange_kind::sized> //
  358. operator()(I i, S s, detail::iter_size_t<I> n) const
  359. {
  360. return {i, s, n};
  361. }
  362. template(typename R)(
  363. requires borrowed_range<R>)
  364. constexpr auto operator()(R && r) const
  365. -> subrange<iterator_t<R>, sentinel_t<R>,
  366. (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
  367. ? subrange_kind::sized
  368. : subrange_kind::unsized>
  369. {
  370. return {(R &&) r};
  371. }
  372. template(typename R)(
  373. requires borrowed_range<R>)
  374. constexpr subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized> //
  375. operator()(R && r, detail::iter_size_t<iterator_t<R>> n) const
  376. {
  377. return {(R &&) r, n};
  378. }
  379. };
  380. /// \relates make_subrange_fn
  381. /// \ingroup group-views
  382. RANGES_INLINE_VARIABLE(make_subrange_fn, make_subrange)
  383. template<typename R>
  384. using borrowed_subrange_t = detail::maybe_dangling_<R, subrange<iterator_t<R>>>;
  385. template<typename R>
  386. using safe_subrange_t RANGES_DEPRECATED("Use borrowed_subrange_t instead.") =
  387. borrowed_subrange_t<R>;
  388. namespace cpp20
  389. {
  390. using ranges::subrange_kind;
  391. template(typename I, //
  392. typename S = I, //
  393. subrange_kind K = //
  394. static_cast<subrange_kind>( //
  395. detail::is_sized_sentinel_<S, I>()))(
  396. requires input_or_output_iterator<I> AND sentinel_for<S, I> AND
  397. (K == subrange_kind::sized || !sized_sentinel_for<S, I>)) //
  398. using subrange = ranges::subrange<I, S, K>;
  399. using ranges::borrowed_subrange_t;
  400. template<typename R>
  401. using safe_subrange_t RANGES_DEPRECATED("Use borrowed_subrange_t instead.") =
  402. borrowed_subrange_t<R>;
  403. } // namespace cpp20
  404. /// @}
  405. } // namespace ranges
  406. RANGES_DIAGNOSTIC_PUSH
  407. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  408. namespace std
  409. {
  410. template<typename I, typename S, ::ranges::subrange_kind K>
  411. struct tuple_size<::ranges::subrange<I, S, K>> : std::integral_constant<size_t, 2>
  412. {};
  413. template<typename I, typename S, ::ranges::subrange_kind K>
  414. struct tuple_element<0, ::ranges::subrange<I, S, K>>
  415. {
  416. using type = I;
  417. };
  418. template<typename I, typename S, ::ranges::subrange_kind K>
  419. struct tuple_element<1, ::ranges::subrange<I, S, K>>
  420. {
  421. using type = S;
  422. };
  423. } // namespace std
  424. RANGES_DIAGNOSTIC_POP
  425. #include <range/v3/detail/epilogue.hpp>
  426. #endif