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.

iterator_range.hpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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_ITERATOR_RANGE_HPP
  14. #define RANGES_V3_ITERATOR_RANGE_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <concepts/concepts.hpp>
  19. #include <range/v3/range_fwd.hpp>
  20. #include <range/v3/iterator/concepts.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/iterator/unreachable_sentinel.hpp>
  23. #include <range/v3/utility/static_const.hpp>
  24. #include <range/v3/view/interface.hpp>
  25. RANGES_DEPRECATED_HEADER(
  26. "This header is deprecated. Please switch to subrange in "
  27. "<range/v3/view/subrange.hpp>.")
  28. namespace ranges
  29. {
  30. /// \addtogroup group-views
  31. /// @{
  32. /// \cond
  33. namespace _iterator_range_
  34. {
  35. struct adl_hook_
  36. {};
  37. // A temporary iterator_range can be safely passed to ranges::begin and
  38. // ranges::end.
  39. template<class I, class S>
  40. constexpr I begin(iterator_range<I, S> && r) noexcept(
  41. std::is_nothrow_copy_constructible<I>::value)
  42. {
  43. return r.begin();
  44. }
  45. template<class I, class S>
  46. constexpr I begin(iterator_range<I, S> const && r) noexcept(
  47. std::is_nothrow_copy_constructible<I>::value)
  48. {
  49. return r.begin();
  50. }
  51. template<class I, class S>
  52. constexpr S end(iterator_range<I, S> && r) noexcept(
  53. std::is_nothrow_copy_constructible<S>::value)
  54. {
  55. return r.end();
  56. }
  57. template<class I, class S>
  58. constexpr S end(iterator_range<I, S> const && r) noexcept(
  59. std::is_nothrow_copy_constructible<S>::value)
  60. {
  61. return r.end();
  62. }
  63. // A temporary sized_iterator_range can be safely passed to ranges::begin and
  64. // ranges::end.
  65. template<class I, class S>
  66. constexpr I begin(sized_iterator_range<I, S> && r) noexcept(
  67. std::is_nothrow_copy_constructible<I>::value)
  68. {
  69. return r.begin();
  70. }
  71. template<class I, class S>
  72. constexpr I begin(sized_iterator_range<I, S> const && r) noexcept(
  73. std::is_nothrow_copy_constructible<I>::value)
  74. {
  75. return r.begin();
  76. }
  77. template<class I, class S>
  78. constexpr S end(sized_iterator_range<I, S> && r) noexcept(
  79. std::is_nothrow_copy_constructible<S>::value)
  80. {
  81. return r.end();
  82. }
  83. template<class I, class S>
  84. constexpr S end(sized_iterator_range<I, S> const && r) noexcept(
  85. std::is_nothrow_copy_constructible<S>::value)
  86. {
  87. return r.end();
  88. }
  89. } // namespace _iterator_range_
  90. /// \endcond
  91. template<typename I, typename S /*= I*/>
  92. struct RANGES_EMPTY_BASES iterator_range
  93. : view_interface<iterator_range<I, S>,
  94. same_as<S, unreachable_sentinel_t> ? infinite : unknown>
  95. , compressed_pair<I, S>
  96. , _iterator_range_::adl_hook_
  97. {
  98. private:
  99. template<typename, typename>
  100. friend struct iterator_range;
  101. template<typename, typename>
  102. friend struct sized_iterator_range;
  103. compressed_pair<I, S> & base() noexcept
  104. {
  105. return *this;
  106. }
  107. compressed_pair<I, S> const & base() const noexcept
  108. {
  109. return *this;
  110. }
  111. using compressed_pair<I, S>::first;
  112. using compressed_pair<I, S>::second;
  113. public:
  114. using iterator = I;
  115. using sentinel = S;
  116. /// \cond
  117. using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
  118. /// \endcond
  119. constexpr I & begin() &
  120. {
  121. return this->first();
  122. }
  123. constexpr I const & begin() const &
  124. {
  125. return this->first();
  126. }
  127. constexpr S & end() &
  128. {
  129. return this->second();
  130. }
  131. constexpr S const & end() const &
  132. {
  133. return this->second();
  134. }
  135. iterator_range() = default;
  136. constexpr iterator_range(I first, S last)
  137. : compressed_pair<I, S>{detail::move(first), detail::move(last)}
  138. {}
  139. template<typename X, typename Y>
  140. constexpr CPP_ctor(iterator_range)(iterator_range<X, Y> rng)( //
  141. requires constructible_from<I, X> && constructible_from<S, Y>)
  142. : compressed_pair<I, S>{detail::move(rng.begin()), detail::move(rng.end())}
  143. {}
  144. template<typename X, typename Y>
  145. explicit constexpr CPP_ctor(iterator_range)(std::pair<X, Y> rng)( //
  146. requires constructible_from<I, X> && constructible_from<S, Y>)
  147. : compressed_pair<I, S>{detail::move(rng.first), detail::move(rng.second)}
  148. {}
  149. template<typename X, typename Y>
  150. auto operator=(iterator_range<X, Y> rng) -> CPP_ret(iterator_range &)( //
  151. requires assignable_from<I &, X> && assignable_from<S &, Y>)
  152. {
  153. base().first() = std::move(rng.base()).first();
  154. base().second() = std::move(rng.base()).second();
  155. return *this;
  156. }
  157. CPP_template(typename X, typename Y)( //
  158. requires convertible_to<I, X> && convertible_to<S, Y>) //
  159. constexpr
  160. operator std::pair<X, Y>() const
  161. {
  162. return {base().first(), base().second()};
  163. }
  164. constexpr bool empty() const
  165. {
  166. return base().first() == base().second();
  167. }
  168. };
  169. // Like iterator_range, but with a known size. The first and second members
  170. // are private to prevent inadvertent violations of the class invariant.
  171. //
  172. // Class invariant:
  173. // distance(begin(), end()) == size()
  174. //
  175. template<typename I, typename S /* = I */>
  176. struct sized_iterator_range
  177. : view_interface<sized_iterator_range<I, S>, finite>
  178. , _iterator_range_::adl_hook_
  179. {
  180. using size_type = detail::iter_size_t<I>;
  181. using iterator = I;
  182. using sentinel = S;
  183. #ifndef RANGES_DOXYGEN_INVOKED
  184. using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
  185. #endif
  186. private:
  187. template<typename X, typename Y>
  188. friend struct sized_iterator_range;
  189. iterator_range<I, S> rng_;
  190. size_type size_;
  191. public:
  192. sized_iterator_range() = default;
  193. RANGES_NDEBUG_CONSTEXPR sized_iterator_range(I first, S last, size_type size)
  194. : rng_{detail::move(first), detail::move(last)}
  195. , size_(size)
  196. {
  197. #ifndef NDEBUG
  198. RANGES_ASSERT(!(bool)forward_iterator<I> ||
  199. static_cast<size_type>(ranges::distance(rng_)) == size_);
  200. #endif
  201. }
  202. template<typename X, typename Y>
  203. RANGES_NDEBUG_CONSTEXPR CPP_ctor(sized_iterator_range)(std::pair<X, Y> rng,
  204. size_type size)( //
  205. requires constructible_from<I, X> && constructible_from<S, Y>)
  206. : sized_iterator_range{detail::move(rng).first, detail::move(rng).second, size}
  207. {}
  208. template<typename X, typename Y>
  209. RANGES_NDEBUG_CONSTEXPR CPP_ctor(sized_iterator_range)(iterator_range<X, Y> rng,
  210. size_type size)( //
  211. requires constructible_from<I, X> && constructible_from<S, Y>)
  212. : sized_iterator_range{detail::move(rng).first(),
  213. detail::move(rng).second,
  214. size}
  215. {}
  216. template<typename X, typename Y>
  217. RANGES_NDEBUG_CONSTEXPR CPP_ctor(sized_iterator_range)(
  218. sized_iterator_range<X, Y> rng)( //
  219. requires constructible_from<I, X> && constructible_from<S, Y>)
  220. : sized_iterator_range{detail::move(rng).rng_.first(),
  221. detail::move(rng).rng_.second,
  222. rng.size_}
  223. {}
  224. template<typename X, typename Y>
  225. auto operator=(sized_iterator_range<X, Y> rng)
  226. -> CPP_ret(sized_iterator_range &)( //
  227. requires assignable_from<I &, X> && assignable_from<S &, Y>)
  228. {
  229. rng_ = detail::move(rng).rng_;
  230. size_ = rng.size_;
  231. return *this;
  232. }
  233. I begin() const
  234. {
  235. return rng_.begin();
  236. }
  237. S end() const
  238. {
  239. return rng_.end();
  240. }
  241. size_type size() const noexcept
  242. {
  243. return size_;
  244. }
  245. CPP_template(typename X, typename Y)( //
  246. requires convertible_to<I, X> && convertible_to<S, Y>) //
  247. constexpr
  248. operator std::pair<X, Y>() const
  249. {
  250. return rng_;
  251. }
  252. CPP_template(typename X, typename Y)( //
  253. requires convertible_to<I, X> && convertible_to<S, Y>) //
  254. constexpr
  255. operator iterator_range<X, Y>() const
  256. {
  257. return rng_;
  258. }
  259. constexpr operator iterator_range<I, S> const &() const & noexcept
  260. {
  261. return rng_;
  262. }
  263. // clang-format off
  264. /// Tuple-like access for `sized_iterator_range`
  265. CPP_template(std::size_t N)( //
  266. requires (N < 2)) //
  267. friend constexpr auto CPP_auto_fun(get)(sized_iterator_range const &p)
  268. (
  269. // return ranges::get<N>(p.rng_)
  270. return ranges::get<N>(p.*&sized_iterator_range::rng_) // makes clang happy
  271. )
  272. // clang-format on
  273. /// \overload
  274. template<std::size_t N>
  275. friend constexpr auto get(sized_iterator_range const & p) noexcept
  276. -> CPP_ret(size_type)( //
  277. requires(N == 2))
  278. {
  279. return p.size();
  280. }
  281. };
  282. struct make_iterator_range_fn
  283. {
  284. /// \return `{first, last}`
  285. template<typename I, typename S>
  286. constexpr auto operator()(I first, S last) const
  287. -> CPP_ret(iterator_range<I, S>)( //
  288. requires sentinel_for<S, I>)
  289. {
  290. return {detail::move(first), detail::move(last)};
  291. }
  292. /// \return `{first, last, size}`
  293. template<typename I, typename S>
  294. constexpr auto operator()(I first, S last, detail::iter_size_t<I> sz) const
  295. -> CPP_ret(sized_iterator_range<I, S>)( //
  296. requires sentinel_for<S, I>)
  297. {
  298. return {detail::move(first), detail::move(last), sz};
  299. }
  300. };
  301. /// \sa `make_iterator_range_fn`
  302. RANGES_INLINE_VARIABLE(make_iterator_range_fn, make_iterator_range)
  303. // TODO add specialization of range_cardinality for when we can determine the range is
  304. // infinite
  305. /// @}
  306. } // namespace ranges
  307. // The standard is inconsistent about whether these are classes or structs
  308. RANGES_DIAGNOSTIC_PUSH
  309. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  310. /// \cond
  311. namespace std
  312. {
  313. template<typename I, typename S>
  314. struct tuple_size<::ranges::iterator_range<I, S>> : std::integral_constant<size_t, 2>
  315. {};
  316. template<typename I, typename S>
  317. struct tuple_element<0, ::ranges::iterator_range<I, S>>
  318. {
  319. using type = I;
  320. };
  321. template<typename I, typename S>
  322. struct tuple_element<1, ::ranges::iterator_range<I, S>>
  323. {
  324. using type = S;
  325. };
  326. template<typename I, typename S>
  327. struct tuple_size<::ranges::sized_iterator_range<I, S>>
  328. : std::integral_constant<size_t, 3>
  329. {};
  330. template<typename I, typename S>
  331. struct tuple_element<0, ::ranges::sized_iterator_range<I, S>>
  332. {
  333. using type = I;
  334. };
  335. template<typename I, typename S>
  336. struct tuple_element<1, ::ranges::sized_iterator_range<I, S>>
  337. {
  338. using type = S;
  339. };
  340. template<typename I, typename S>
  341. struct tuple_element<2, ::ranges::sized_iterator_range<I, S>>
  342. {
  343. using type = typename ::ranges::sized_iterator_range<I, S>::size_type;
  344. };
  345. } // namespace std
  346. /// \endcond
  347. RANGES_DIAGNOSTIC_POP
  348. #endif