iterator_range.hpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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. #include <range/v3/detail/prologue.hpp>
  29. namespace ranges
  30. {
  31. /// \addtogroup group-views
  32. /// @{
  33. template<typename I, typename S>
  34. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<iterator_range<I, S>> = true;
  35. template<typename I, typename S>
  36. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<sized_iterator_range<I, S>> =
  37. true;
  38. template<typename I, typename S /*= I*/>
  39. struct RANGES_EMPTY_BASES iterator_range
  40. : view_interface<iterator_range<I, S>,
  41. same_as<S, unreachable_sentinel_t> ? infinite : unknown>
  42. , compressed_pair<I, S>
  43. {
  44. private:
  45. template<typename, typename>
  46. friend struct iterator_range;
  47. template<typename, typename>
  48. friend struct sized_iterator_range;
  49. compressed_pair<I, S> & base() noexcept
  50. {
  51. return *this;
  52. }
  53. compressed_pair<I, S> const & base() const noexcept
  54. {
  55. return *this;
  56. }
  57. using compressed_pair<I, S>::first;
  58. using compressed_pair<I, S>::second;
  59. public:
  60. using iterator = I;
  61. using sentinel = S;
  62. /// \cond
  63. using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
  64. /// \endcond
  65. constexpr I & begin() &
  66. {
  67. return this->first();
  68. }
  69. constexpr I const & begin() const &
  70. {
  71. return this->first();
  72. }
  73. constexpr S & end() &
  74. {
  75. return this->second();
  76. }
  77. constexpr S const & end() const &
  78. {
  79. return this->second();
  80. }
  81. iterator_range() = default;
  82. constexpr iterator_range(I first, S last)
  83. : compressed_pair<I, S>{detail::move(first), detail::move(last)}
  84. {}
  85. template(typename X, typename Y)(
  86. requires constructible_from<I, X> AND constructible_from<S, Y>)
  87. constexpr iterator_range(iterator_range<X, Y> rng)
  88. : compressed_pair<I, S>{detail::move(rng.begin()), detail::move(rng.end())}
  89. {}
  90. template(typename X, typename Y)(
  91. requires constructible_from<I, X> AND constructible_from<S, Y>)
  92. constexpr explicit iterator_range(std::pair<X, Y> rng)
  93. : compressed_pair<I, S>{detail::move(rng.first), detail::move(rng.second)}
  94. {}
  95. template(typename X, typename Y)(
  96. requires assignable_from<I &, X> AND assignable_from<S &, Y>)
  97. iterator_range & operator=(iterator_range<X, Y> rng)
  98. {
  99. base().first() = std::move(rng.base()).first();
  100. base().second() = std::move(rng.base()).second();
  101. return *this;
  102. }
  103. template(typename X, typename Y)(
  104. requires convertible_to<I, X> AND convertible_to<S, Y>)
  105. constexpr operator std::pair<X, Y>() const
  106. {
  107. return {base().first(), base().second()};
  108. }
  109. constexpr bool empty() const
  110. {
  111. return base().first() == base().second();
  112. }
  113. };
  114. // Like iterator_range, but with a known size. The first and second members
  115. // are private to prevent inadvertent violations of the class invariant.
  116. //
  117. // Class invariant:
  118. // distance(begin(), end()) == size()
  119. //
  120. template<typename I, typename S /* = I */>
  121. struct sized_iterator_range
  122. : view_interface<sized_iterator_range<I, S>, finite>
  123. {
  124. using size_type = detail::iter_size_t<I>;
  125. using iterator = I;
  126. using sentinel = S;
  127. #ifndef RANGES_DOXYGEN_INVOKED
  128. using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
  129. #endif
  130. private:
  131. template<typename X, typename Y>
  132. friend struct sized_iterator_range;
  133. iterator_range<I, S> rng_;
  134. size_type size_;
  135. public:
  136. sized_iterator_range() = default;
  137. RANGES_NDEBUG_CONSTEXPR sized_iterator_range(I first, S last, size_type size)
  138. : rng_{detail::move(first), detail::move(last)}
  139. , size_(size)
  140. {
  141. #ifndef NDEBUG
  142. RANGES_ASSERT(!(bool)forward_iterator<I> ||
  143. static_cast<size_type>(ranges::distance(rng_)) == size_);
  144. #endif
  145. }
  146. template(typename X, typename Y)(
  147. requires constructible_from<I, X> AND constructible_from<S, Y>)
  148. RANGES_NDEBUG_CONSTEXPR sized_iterator_range(std::pair<X, Y> rng, size_type size)
  149. : sized_iterator_range{detail::move(rng).first, detail::move(rng).second, size}
  150. {}
  151. template(typename X, typename Y)(
  152. requires constructible_from<I, X> AND constructible_from<S, Y>)
  153. RANGES_NDEBUG_CONSTEXPR sized_iterator_range(iterator_range<X, Y> rng,
  154. size_type size)
  155. : sized_iterator_range{detail::move(rng).first(),
  156. detail::move(rng).second,
  157. size}
  158. {}
  159. template(typename X, typename Y)(
  160. requires constructible_from<I, X> AND constructible_from<S, Y>)
  161. RANGES_NDEBUG_CONSTEXPR sized_iterator_range(sized_iterator_range<X, Y> rng)
  162. : sized_iterator_range{detail::move(rng).rng_.first(),
  163. detail::move(rng).rng_.second,
  164. rng.size_}
  165. {}
  166. template(typename X, typename Y)(
  167. requires assignable_from<I &, X> AND assignable_from<S &, Y>)
  168. sized_iterator_range & operator=(sized_iterator_range<X, Y> rng)
  169. {
  170. rng_ = detail::move(rng).rng_;
  171. size_ = rng.size_;
  172. return *this;
  173. }
  174. I begin() const
  175. {
  176. return rng_.begin();
  177. }
  178. S end() const
  179. {
  180. return rng_.end();
  181. }
  182. size_type size() const noexcept
  183. {
  184. return size_;
  185. }
  186. template(typename X, typename Y)(
  187. requires convertible_to<I, X> AND convertible_to<S, Y>)
  188. constexpr operator std::pair<X, Y>() const
  189. {
  190. return rng_;
  191. }
  192. template(typename X, typename Y)(
  193. requires convertible_to<I, X> AND convertible_to<S, Y>)
  194. constexpr operator iterator_range<X, Y>() const
  195. {
  196. return rng_;
  197. }
  198. constexpr operator iterator_range<I, S> const &() const & noexcept
  199. {
  200. return rng_;
  201. }
  202. // clang-format off
  203. /// Tuple-like access for `sized_iterator_range`
  204. template(std::size_t N)(
  205. requires (N < 2)) //
  206. friend constexpr auto CPP_auto_fun(get)(sized_iterator_range const &p)
  207. (
  208. // return ranges::get<N>(p.rng_)
  209. return ranges::get<N>(p.*&sized_iterator_range::rng_) // makes clang happy
  210. )
  211. // clang-format on
  212. /// \overload
  213. template(std::size_t N)(
  214. requires (N == 2)) //
  215. friend constexpr size_type get(sized_iterator_range const & p) noexcept
  216. {
  217. return p.size();
  218. }
  219. };
  220. struct make_iterator_range_fn
  221. {
  222. /// \return `{first, last}`
  223. template(typename I, typename S)(
  224. requires sentinel_for<S, I>)
  225. constexpr iterator_range<I, S> operator()(I first, S last) const
  226. {
  227. return {detail::move(first), detail::move(last)};
  228. }
  229. /// \return `{first, last, size}`
  230. template(typename I, typename S)(
  231. requires sentinel_for<S, I>)
  232. constexpr sized_iterator_range<I, S> //
  233. operator()(I first, S last, detail::iter_size_t<I> sz) const
  234. {
  235. return {detail::move(first), detail::move(last), sz};
  236. }
  237. };
  238. /// \sa `make_iterator_range_fn`
  239. RANGES_INLINE_VARIABLE(make_iterator_range_fn, make_iterator_range)
  240. // TODO add specialization of range_cardinality for when we can determine the range is
  241. // infinite
  242. /// @}
  243. } // namespace ranges
  244. // The standard is inconsistent about whether these are classes or structs
  245. RANGES_DIAGNOSTIC_PUSH
  246. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  247. /// \cond
  248. namespace std
  249. {
  250. template<typename I, typename S>
  251. struct tuple_size<::ranges::iterator_range<I, S>> : std::integral_constant<size_t, 2>
  252. {};
  253. template<typename I, typename S>
  254. struct tuple_element<0, ::ranges::iterator_range<I, S>>
  255. {
  256. using type = I;
  257. };
  258. template<typename I, typename S>
  259. struct tuple_element<1, ::ranges::iterator_range<I, S>>
  260. {
  261. using type = S;
  262. };
  263. template<typename I, typename S>
  264. struct tuple_size<::ranges::sized_iterator_range<I, S>>
  265. : std::integral_constant<size_t, 3>
  266. {};
  267. template<typename I, typename S>
  268. struct tuple_element<0, ::ranges::sized_iterator_range<I, S>>
  269. {
  270. using type = I;
  271. };
  272. template<typename I, typename S>
  273. struct tuple_element<1, ::ranges::sized_iterator_range<I, S>>
  274. {
  275. using type = S;
  276. };
  277. template<typename I, typename S>
  278. struct tuple_element<2, ::ranges::sized_iterator_range<I, S>>
  279. {
  280. using type = typename ::ranges::sized_iterator_range<I, S>::size_type;
  281. };
  282. } // namespace std
  283. /// \endcond
  284. RANGES_DIAGNOSTIC_POP
  285. #include <range/v3/detail/epilogue.hpp>
  286. #endif