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.

502 lines
17KB

  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. namespace ranges
  29. {
  30. /// \addtogroup group-views
  31. /// @{
  32. enum class subrange_kind : bool
  33. {
  34. unsized,
  35. sized
  36. };
  37. /// \cond
  38. namespace detail
  39. {
  40. template<std::size_t N, typename T>
  41. using tuple_element_fun_t = void (*)(meta::_t<std::tuple_element<N, T>> const &);
  42. // clang-format off
  43. CPP_def
  44. (
  45. template(typename From, typename To)
  46. concept convertible_to_not_slicing_,
  47. convertible_to<From, To> &&
  48. // A conversion is a slicing conversion if the source and the destination
  49. // are both pointers, and if the pointed-to types differ after removing
  50. // cv qualifiers.
  51. (!(std::is_pointer<decay_t<From>>::value &&
  52. std::is_pointer<decay_t<To>>::value &&
  53. not_same_as_<meta::_t<std::remove_pointer<decay_t<From>>>,
  54. meta::_t<std::remove_pointer<decay_t<To>>>>))
  55. );
  56. CPP_def
  57. (
  58. template(typename T)
  59. concept pair_like_gcc_bugs_3_,
  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. );
  66. CPP_def
  67. (
  68. template(typename T)
  69. concept pair_like_gcc_bugs_2_,
  70. derived_from<std::tuple_size<T>, meta::size_t<2>> &&
  71. pair_like_gcc_bugs_3_<T>
  72. );
  73. CPP_def
  74. (
  75. template(typename T)
  76. concept pair_like_gcc_bugs_,
  77. ranges::defer::type<meta::_t<std::tuple_size<T>>> &&
  78. defer::pair_like_gcc_bugs_2_<T>
  79. );
  80. CPP_def
  81. (
  82. template(typename T)
  83. concept get_first_and_second_,
  84. requires(T &t)
  85. (
  86. get<0>(t),
  87. get<1>(t)
  88. )
  89. );
  90. CPP_def
  91. (
  92. template(typename T)
  93. concept pair_like_,
  94. (!std::is_reference<T>::value) &&
  95. (defer::get_first_and_second_<T> &&
  96. defer::pair_like_gcc_bugs_<T>)
  97. );
  98. // clang-format on
  99. // Short-circuit the PairLike concept for things known to be pairs:
  100. template<typename T>
  101. struct pair_like : meta::bool_<pair_like_<T>>
  102. {};
  103. template<typename F, typename S>
  104. struct pair_like<std::pair<F, S>> : meta::bool_<true>
  105. {};
  106. template<typename... Ts>
  107. struct pair_like<std::tuple<Ts...>> : meta::bool_<sizeof...(Ts) == 2u>
  108. {};
  109. // clang-format off
  110. CPP_def
  111. (
  112. template(typename T, typename U, typename V)
  113. concept pair_like_convertible_from_gcc_bugs_,
  114. convertible_to_not_slicing_<U, meta::_t<std::tuple_element<0, T>>> &&
  115. convertible_to<V, meta::_t<std::tuple_element<1, T>>>
  116. );
  117. CPP_def
  118. (
  119. template(typename T, typename U, typename V)
  120. concept pair_like_convertible_from_,
  121. (!range<T>) &&
  122. constructible_from<T, U, V> &&
  123. (ranges::defer::is_true<pair_like<uncvref_t<T>>::value> &&
  124. defer::pair_like_convertible_from_gcc_bugs_<T, U, V>)
  125. );
  126. CPP_def
  127. (
  128. template(typename R, typename I, typename S)
  129. concept range_convertible_to_,
  130. forwarding_range_<R> &&
  131. convertible_to_not_slicing_<iterator_t<R>, I> &&
  132. convertible_to<sentinel_t<R>, S>
  133. );
  134. // clang-format on
  135. template<typename S, typename I>
  136. constexpr auto is_sized_sentinel_() noexcept -> CPP_ret(bool)( //
  137. requires sentinel_for<S, I>)
  138. {
  139. return (bool)sized_sentinel_for<S, I>;
  140. }
  141. template<subrange_kind K, typename S, typename I>
  142. constexpr bool store_size_() noexcept
  143. {
  144. return K == subrange_kind::sized && !(bool)sized_sentinel_for<S, I>;
  145. }
  146. } // namespace detail
  147. /// \endcond
  148. template<typename I, typename S = I,
  149. subrange_kind K =
  150. static_cast<subrange_kind>(detail::is_sized_sentinel_<S, I>())>
  151. struct subrange;
  152. /// \cond
  153. namespace _subrange_
  154. {
  155. struct adl_hook
  156. {};
  157. // A temporary subrange can be safely passed to ranges::begin and ranges::end.
  158. template<typename I, typename S, subrange_kind K>
  159. constexpr I begin(subrange<I, S, K> && r) noexcept(
  160. std::is_nothrow_copy_constructible<I>::value)
  161. {
  162. return r.begin();
  163. }
  164. template<typename I, typename S, subrange_kind K>
  165. constexpr I begin(subrange<I, S, K> const && r) noexcept(
  166. std::is_nothrow_copy_constructible<I>::value)
  167. {
  168. return r.begin();
  169. }
  170. template<typename I, typename S, subrange_kind K>
  171. constexpr S end(subrange<I, S, K> && r) noexcept(
  172. std::is_nothrow_copy_constructible<S>::value)
  173. {
  174. return r.end();
  175. }
  176. template<typename I, typename S, subrange_kind K>
  177. constexpr S end(subrange<I, S, K> const && r) noexcept(
  178. std::is_nothrow_copy_constructible<S>::value)
  179. {
  180. return r.end();
  181. }
  182. template<std::size_t N, typename I, typename S, subrange_kind K>
  183. constexpr auto get(subrange<I, S, K> const & r) -> CPP_ret(I)( //
  184. requires(N == 0))
  185. {
  186. return r.begin();
  187. }
  188. template<std::size_t N, typename I, typename S, subrange_kind K>
  189. constexpr auto get(subrange<I, S, K> const & r) -> CPP_ret(S)( //
  190. requires(N == 1))
  191. {
  192. return r.end();
  193. }
  194. } // namespace _subrange_
  195. /// \endcond
  196. template<typename I, typename S, subrange_kind K>
  197. struct subrange
  198. : view_interface<subrange<I, S, K>,
  199. same_as<S, unreachable_sentinel_t>
  200. ? infinite
  201. : K == subrange_kind::sized ? finite : unknown>
  202. , private _subrange_::adl_hook
  203. {
  204. CPP_assert(input_or_output_iterator<I>);
  205. CPP_assert(sentinel_for<S, I>);
  206. CPP_assert(K == subrange_kind::sized || !sized_sentinel_for<S, I>);
  207. CPP_assert(K != subrange_kind::sized || !same_as<S, unreachable_sentinel_t>);
  208. using size_type = detail::iter_size_t<I>;
  209. using iterator = I;
  210. using sentinel = S;
  211. subrange() = default;
  212. template<typename I2>
  213. constexpr CPP_ctor(subrange)(I2 && i, S s)( //
  214. requires detail::convertible_to_not_slicing_<I2, I> &&
  215. (!detail::store_size_<K, S, I>()))
  216. : data_{static_cast<I2 &&>(i), std::move(s)}
  217. {}
  218. template<typename I2>
  219. constexpr CPP_ctor(subrange)(I2 && i, S s, size_type n)( //
  220. requires detail::convertible_to_not_slicing_<I2, I> &&
  221. (detail::store_size_<K, S, I>()))
  222. : data_{static_cast<I2 &&>(i), std::move(s), n}
  223. {
  224. if(RANGES_CONSTEXPR_IF((bool)random_access_iterator<I>))
  225. {
  226. using D = iter_difference_t<I>;
  227. RANGES_EXPECT(n <= (size_type)std::numeric_limits<D>::max());
  228. RANGES_EXPECT(ranges::next(first_(), (D)n) == last_());
  229. }
  230. }
  231. template<typename I2>
  232. constexpr CPP_ctor(subrange)(I2 && i, S s, size_type n)( //
  233. requires detail::convertible_to_not_slicing_<I2, I> &&
  234. sized_sentinel_for<S, I>)
  235. : data_{static_cast<I2 &&>(i), std::move(s)}
  236. {
  237. RANGES_EXPECT(static_cast<size_type>(last_() - first_()) == n);
  238. }
  239. template<typename R>
  240. constexpr CPP_ctor(subrange)(R && r)(
  241. requires defer::not_same_as_<R, subrange> &&
  242. detail::defer::range_convertible_to_<R, I, S> &&
  243. defer::is_true<!detail::store_size_<K, S, I>()>)
  244. : subrange{ranges::begin(r), ranges::end(r)}
  245. {}
  246. template<typename R>
  247. constexpr CPP_ctor(subrange)(R && r)(
  248. requires defer::not_same_as_<R, subrange> &&
  249. detail::defer::range_convertible_to_<R, I, S> && defer::is_true<
  250. detail::store_size_<K, S, I>()> && defer::sized_range<R>)
  251. : subrange{ranges::begin(r), ranges::end(r), ranges::size(r)}
  252. {}
  253. template<typename R>
  254. constexpr CPP_ctor(subrange)(R && r, size_type n)(
  255. requires detail::range_convertible_to_<R, I, S> &&
  256. (K == subrange_kind::sized))
  257. : subrange{ranges::begin(r), ranges::end(r), n}
  258. {
  259. if(RANGES_CONSTEXPR_IF((bool)sized_range<R>))
  260. {
  261. RANGES_EXPECT(n == ranges::size(r));
  262. }
  263. }
  264. /// Implicit conversion to something that looks like a container.
  265. CPP_template(typename Container)( //
  266. requires detail::convertible_to_container<subrange const, Container>) //
  267. constexpr
  268. operator Container() const
  269. {
  270. return ranges::to<Container>(*this);
  271. }
  272. CPP_template(typename PairLike)( //
  273. requires defer::not_same_as_<PairLike, subrange> &&
  274. detail::defer::pair_like_convertible_from_<PairLike, const I &,
  275. const S &>) //
  276. constexpr
  277. operator PairLike() const
  278. {
  279. return PairLike(first_(), last_());
  280. }
  281. constexpr I begin() const noexcept(std::is_nothrow_copy_constructible<I>::value)
  282. {
  283. return first_();
  284. }
  285. constexpr S end() const noexcept(std::is_nothrow_copy_constructible<S>::value)
  286. {
  287. return last_();
  288. }
  289. constexpr bool empty() const
  290. {
  291. return first_() == last_();
  292. }
  293. CPP_member
  294. constexpr auto size() const -> CPP_ret(size_type)( //
  295. requires(K == subrange_kind::sized))
  296. {
  297. return get_size_();
  298. }
  299. RANGES_NODISCARD
  300. constexpr subrange next(iter_difference_t<I> n = 1) const
  301. {
  302. auto tmp = *this;
  303. tmp.advance(n);
  304. return tmp;
  305. }
  306. CPP_member
  307. RANGES_NODISCARD constexpr auto prev(iter_difference_t<I> n = 1) const
  308. -> CPP_ret(subrange)( //
  309. requires bidirectional_iterator<I>)
  310. {
  311. auto tmp = *this;
  312. tmp.advance(-n);
  313. return tmp;
  314. }
  315. constexpr subrange & advance(iter_difference_t<I> n)
  316. {
  317. set_size_(get_size_() -
  318. static_cast<size_type>(n - ranges::advance(first_(), n, last_())));
  319. return *this;
  320. }
  321. private:
  322. detail::if_then_t<detail::store_size_<K, S, I>(), std::tuple<I, S, size_type>,
  323. std::tuple<I, S>>
  324. data_;
  325. constexpr I & first_() noexcept
  326. {
  327. return std::get<0>(data_);
  328. }
  329. constexpr const I & first_() const noexcept
  330. {
  331. return std::get<0>(data_);
  332. }
  333. constexpr S & last_() noexcept
  334. {
  335. return std::get<1>(data_);
  336. }
  337. constexpr const S & last_() const noexcept
  338. {
  339. return std::get<1>(data_);
  340. }
  341. CPP_member
  342. constexpr auto get_size_() const -> CPP_ret(size_type)( //
  343. requires sized_sentinel_for<S, I>)
  344. {
  345. return static_cast<size_type>(last_() - first_());
  346. }
  347. CPP_member
  348. constexpr auto get_size_() const noexcept -> CPP_ret(size_type)( //
  349. requires(detail::store_size_<K, S, I>()))
  350. {
  351. return std::get<2>(data_);
  352. }
  353. static constexpr void set_size_(...) noexcept
  354. {}
  355. CPP_member
  356. constexpr auto set_size_(size_type n) noexcept -> CPP_ret(void)( //
  357. requires(detail::store_size_<K, S, I>()))
  358. {
  359. std::get<2>(data_) = n;
  360. }
  361. };
  362. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  363. template<typename I, typename S>
  364. subrange(I, S)->subrange<I, S>;
  365. CPP_template(typename I, typename S)( //
  366. requires input_or_output_iterator<I> && sentinel_for<S, I>) //
  367. subrange(I, S, detail::iter_size_t<I>)
  368. ->subrange<I, S, subrange_kind::sized>;
  369. CPP_template(typename R)( //
  370. requires forwarding_range_<R>) //
  371. subrange(R &&)
  372. ->subrange<iterator_t<R>, sentinel_t<R>,
  373. (sized_range<R> ||
  374. sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
  375. ? subrange_kind::sized
  376. : subrange_kind::unsized>;
  377. CPP_template(typename R)( //
  378. requires forwarding_range_<R>) //
  379. subrange(R &&, detail::iter_size_t<iterator_t<R>>)
  380. ->subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
  381. #endif
  382. // in lieu of deduction guides, use make_subrange
  383. struct make_subrange_fn
  384. {
  385. template<typename I, typename S>
  386. constexpr auto operator()(I i, S s) const -> subrange<I, S>
  387. {
  388. return {i, s};
  389. }
  390. template<typename I, typename S>
  391. constexpr auto operator()(I i, S s, detail::iter_size_t<I> n) const
  392. -> CPP_ret(subrange<I, S, subrange_kind::sized>)( //
  393. requires input_or_output_iterator<I> && sentinel_for<S, I>)
  394. {
  395. return {i, s, n};
  396. }
  397. template<typename R>
  398. constexpr auto operator()(R && r) const -> CPP_ret(
  399. subrange<iterator_t<R>, sentinel_t<R>,
  400. (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
  401. ? subrange_kind::sized
  402. : subrange_kind::unsized>)( //
  403. requires forwarding_range_<R>)
  404. {
  405. return {(R &&) r};
  406. }
  407. template<typename R>
  408. constexpr auto operator()(R && r, detail::iter_size_t<iterator_t<R>> n) const
  409. -> CPP_ret(subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>)( //
  410. requires forwarding_range_<R>)
  411. {
  412. return {(R &&) r, n};
  413. }
  414. };
  415. /// \relates make_subrange_fn
  416. /// \ingroup group-views
  417. RANGES_INLINE_VARIABLE(make_subrange_fn, make_subrange)
  418. template<typename R>
  419. using safe_subrange_t = detail::maybe_dangling_<R, subrange<iterator_t<R>>>;
  420. namespace cpp20
  421. {
  422. using ranges::subrange_kind;
  423. CPP_template(typename I, //
  424. typename S = I, //
  425. subrange_kind K = //
  426. static_cast<subrange_kind>( //
  427. detail::is_sized_sentinel_<S, I>()))( //
  428. requires input_or_output_iterator<I> && sentinel_for<S, I> && //
  429. (K == subrange_kind::sized || !sized_sentinel_for<S, I>)) //
  430. using subrange = ranges::subrange<I, S>;
  431. using ranges::safe_subrange_t;
  432. } // namespace cpp20
  433. /// @}
  434. } // namespace ranges
  435. RANGES_DIAGNOSTIC_PUSH
  436. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  437. namespace std
  438. {
  439. template<typename I, typename S, ::ranges::subrange_kind K>
  440. struct tuple_size<::ranges::subrange<I, S, K>> : std::integral_constant<size_t, 2>
  441. {};
  442. template<typename I, typename S, ::ranges::subrange_kind K>
  443. struct tuple_element<0, ::ranges::subrange<I, S, K>>
  444. {
  445. using type = I;
  446. };
  447. template<typename I, typename S, ::ranges::subrange_kind K>
  448. struct tuple_element<1, ::ranges::subrange<I, S, K>>
  449. {
  450. using type = S;
  451. };
  452. } // namespace std
  453. RANGES_DIAGNOSTIC_POP
  454. #endif