range_access.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-present
  5. // Copyright Casey Carter 2016
  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_DETAIL_RANGE_ACCESS_HPP
  15. #define RANGES_V3_DETAIL_RANGE_ACCESS_HPP
  16. #include <cstddef>
  17. #include <utility>
  18. #include <meta/meta.hpp>
  19. #include <concepts/concepts.hpp>
  20. #include <range/v3/range_fwd.hpp>
  21. #include <range/v3/iterator/concepts.hpp>
  22. #include <range/v3/detail/prologue.hpp>
  23. namespace ranges
  24. {
  25. /// \addtogroup group-views
  26. /// @{
  27. struct range_access
  28. {
  29. /// \cond
  30. private:
  31. template<typename T>
  32. static std::false_type single_pass_2_(long);
  33. template<typename T>
  34. static typename T::single_pass single_pass_2_(int);
  35. template<typename T>
  36. struct single_pass_
  37. {
  38. using type = decltype(range_access::single_pass_2_<T>(42));
  39. };
  40. template<typename T>
  41. static std::false_type contiguous_2_(long);
  42. template<typename T>
  43. static typename T::contiguous contiguous_2_(int);
  44. template<typename T>
  45. struct contiguous_
  46. {
  47. using type = decltype(range_access::contiguous_2_<T>(42));
  48. };
  49. template<typename T>
  50. static basic_mixin<T> mixin_base_2_(long);
  51. template<typename T>
  52. static typename T::mixin mixin_base_2_(int);
  53. template<typename Cur>
  54. struct mixin_base_
  55. {
  56. using type = decltype(range_access::mixin_base_2_<Cur>(42));
  57. };
  58. public:
  59. template<typename Cur>
  60. using single_pass_t = meta::_t<single_pass_<Cur>>;
  61. template<typename Cur>
  62. using contiguous_t = meta::_t<contiguous_<Cur>>;
  63. template<typename Cur>
  64. using mixin_base_t = meta::_t<mixin_base_<Cur>>;
  65. // clang-format off
  66. template<typename Rng>
  67. static constexpr auto CPP_auto_fun(begin_cursor)(Rng &rng)
  68. (
  69. return rng.begin_cursor()
  70. )
  71. template<typename Rng>
  72. static constexpr auto CPP_auto_fun(end_cursor)(Rng &rng)
  73. (
  74. return rng.end_cursor()
  75. )
  76. template<typename Rng>
  77. static constexpr auto CPP_auto_fun(begin_adaptor)(Rng &rng)
  78. (
  79. return rng.begin_adaptor()
  80. )
  81. template<typename Rng>
  82. static constexpr auto CPP_auto_fun(end_adaptor)(Rng &rng)
  83. (
  84. return rng.end_adaptor()
  85. )
  86. template<typename Cur>
  87. static constexpr auto CPP_auto_fun(read)(Cur const &pos)
  88. (
  89. return pos.read()
  90. )
  91. template<typename Cur>
  92. static constexpr auto CPP_auto_fun(arrow)(Cur const &pos)
  93. (
  94. return pos.arrow()
  95. )
  96. template<typename Cur>
  97. static constexpr auto CPP_auto_fun(move)(Cur const &pos)
  98. (
  99. return pos.move()
  100. )
  101. template<typename Cur, typename T>
  102. static constexpr auto CPP_auto_fun(write)(Cur &pos, T &&t)
  103. (
  104. return pos.write((T &&) t)
  105. )
  106. template<typename Cur>
  107. static constexpr auto CPP_auto_fun(next)(Cur & pos)
  108. (
  109. return pos.next()
  110. )
  111. template<typename Cur, typename O>
  112. static constexpr auto CPP_auto_fun(equal)(Cur const &pos, O const &other)
  113. (
  114. return pos.equal(other)
  115. )
  116. template<typename Cur>
  117. static constexpr auto CPP_auto_fun(prev)(Cur & pos)
  118. (
  119. return pos.prev()
  120. )
  121. template<typename Cur, typename D>
  122. static constexpr auto CPP_auto_fun(advance)(Cur & pos, D n)
  123. (
  124. return pos.advance(n)
  125. )
  126. template<typename Cur, typename O>
  127. static constexpr auto CPP_auto_fun(distance_to)(Cur const &pos, O const &other)
  128. (
  129. return pos.distance_to(other)
  130. )
  131. private:
  132. template<typename Cur>
  133. using sized_cursor_difference_t = decltype(
  134. range_access::distance_to(std::declval<Cur>(), std::declval<Cur>()));
  135. // clang-format on
  136. template<typename T>
  137. static std::ptrdiff_t cursor_difference_2_(detail::ignore_t);
  138. template<typename T>
  139. static sized_cursor_difference_t<T> cursor_difference_2_(long);
  140. template<typename T>
  141. static typename T::difference_type cursor_difference_2_(int);
  142. template<typename T>
  143. using cursor_reference_t = decltype(std::declval<T const &>().read());
  144. template<typename T>
  145. static meta::id<uncvref_t<cursor_reference_t<T>>> cursor_value_2_(long);
  146. template<typename T>
  147. static meta::id<typename T::value_type> cursor_value_2_(int);
  148. #ifdef RANGES_WORKAROUND_CWG_1554
  149. template<typename Cur>
  150. struct cursor_difference
  151. {
  152. using type = decltype(range_access::cursor_difference_2_<Cur>(42));
  153. };
  154. template<typename Cur>
  155. struct cursor_value : decltype(range_access::cursor_value_2_<Cur>(42))
  156. {};
  157. #endif // RANGES_WORKAROUND_CWG_1554
  158. public:
  159. #ifdef RANGES_WORKAROUND_CWG_1554
  160. template<typename Cur>
  161. using cursor_difference_t = meta::_t<cursor_difference<Cur>>;
  162. template<typename Cur>
  163. using cursor_value_t = meta::_t<cursor_value<Cur>>;
  164. #else // ^^^ workaround ^^^ / vvv no workaround vvv
  165. template<typename Cur>
  166. using cursor_difference_t = decltype(range_access::cursor_difference_2_<Cur>(42));
  167. template<typename Cur>
  168. using cursor_value_t = meta::_t<decltype(range_access::cursor_value_2_<Cur>(42))>;
  169. #endif // RANGES_WORKAROUND_CWG_1554
  170. template<typename Cur>
  171. static constexpr Cur & pos(basic_iterator<Cur> & it) noexcept
  172. {
  173. return it.pos();
  174. }
  175. template<typename Cur>
  176. static constexpr Cur const & pos(basic_iterator<Cur> const & it) noexcept
  177. {
  178. return it.pos();
  179. }
  180. template<typename Cur>
  181. static constexpr Cur && pos(basic_iterator<Cur> && it) noexcept
  182. {
  183. return detail::move(it.pos());
  184. }
  185. template<typename Cur>
  186. static constexpr Cur cursor(basic_iterator<Cur> it)
  187. {
  188. return std::move(it.pos());
  189. }
  190. /// endcond
  191. };
  192. /// @}
  193. /// \cond
  194. namespace detail
  195. {
  196. //
  197. // Concepts that the range cursor must model
  198. // clang-format off
  199. //
  200. /// \concept cursor
  201. /// \brief The \c cursor concept
  202. template<typename T>
  203. CPP_concept cursor =
  204. semiregular<T> && semiregular<range_access::mixin_base_t<T>> &&
  205. constructible_from<range_access::mixin_base_t<T>, T> &&
  206. constructible_from<range_access::mixin_base_t<T>, T const &>;
  207. // Axiom: mixin_base_t<T> has a member get(), accessible to derived classes,
  208. // which perfectly-returns the contained cursor object and does not throw
  209. // exceptions.
  210. /// \concept has_cursor_next_
  211. /// \brief The \c has_cursor_next_ concept
  212. template<typename T>
  213. CPP_requires(has_cursor_next_,
  214. requires(T & t)
  215. (
  216. range_access::next(t)
  217. ));
  218. /// \concept has_cursor_next
  219. /// \brief The \c has_cursor_next concept
  220. template<typename T>
  221. CPP_concept has_cursor_next = CPP_requires_ref(detail::has_cursor_next_, T);
  222. /// \concept sentinel_for_cursor_
  223. /// \brief The \c sentinel_for_cursor_ concept
  224. template<typename S, typename C>
  225. CPP_requires(sentinel_for_cursor_,
  226. requires(S & s, C & c) //
  227. (
  228. range_access::equal(c, s),
  229. concepts::requires_<convertible_to<decltype(
  230. range_access::equal(c, s)), bool>>
  231. ));
  232. /// \concept sentinel_for_cursor
  233. /// \brief The \c sentinel_for_cursor concept
  234. template<typename S, typename C>
  235. CPP_concept sentinel_for_cursor =
  236. semiregular<S> &&
  237. cursor<C> &&
  238. CPP_requires_ref(detail::sentinel_for_cursor_, S, C);
  239. /// \concept readable_cursor_
  240. /// \brief The \c readable_cursor_ concept
  241. template<typename T>
  242. CPP_requires(readable_cursor_,
  243. requires(T & t) //
  244. (
  245. range_access::read(t)
  246. ));
  247. /// \concept readable_cursor
  248. /// \brief The \c readable_cursor concept
  249. template<typename T>
  250. CPP_concept readable_cursor = CPP_requires_ref(detail::readable_cursor_, T);
  251. /// \concept has_cursor_arrow_
  252. /// \brief The \c has_cursor_arrow_ concept
  253. template<typename T>
  254. CPP_requires(has_cursor_arrow_,
  255. requires(T const & t) //
  256. (
  257. range_access::arrow(t)
  258. ));
  259. /// \concept has_cursor_arrow
  260. /// \brief The \c has_cursor_arrow concept
  261. template<typename T>
  262. CPP_concept has_cursor_arrow = CPP_requires_ref(detail::has_cursor_arrow_, T);
  263. /// \concept writable_cursor_
  264. /// \brief The \c writable_cursor_ concept
  265. template<typename T, typename U>
  266. CPP_requires(writable_cursor_,
  267. requires(T & t, U && u) //
  268. (
  269. range_access::write(t, (U &&) u)
  270. ));
  271. /// \concept writable_cursor
  272. /// \brief The \c writable_cursor concept
  273. template<typename T, typename U>
  274. CPP_concept writable_cursor =
  275. CPP_requires_ref(detail::writable_cursor_, T, U);
  276. /// \concept sized_sentinel_for_cursor_
  277. /// \brief The \c sized_sentinel_for_cursor_ concept
  278. template<typename S, typename C>
  279. CPP_requires(sized_sentinel_for_cursor_,
  280. requires(S & s, C & c) //
  281. (
  282. range_access::distance_to(c, s),
  283. concepts::requires_<signed_integer_like_<decltype(
  284. range_access::distance_to(c, s))>>
  285. )
  286. );
  287. /// \concept sized_sentinel_for_cursor
  288. /// \brief The \c sized_sentinel_for_cursor concept
  289. template<typename S, typename C>
  290. CPP_concept sized_sentinel_for_cursor =
  291. sentinel_for_cursor<S, C> &&
  292. CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C);
  293. /// \concept output_cursor
  294. /// \brief The \c output_cursor concept
  295. template<typename T, typename U>
  296. CPP_concept output_cursor =
  297. writable_cursor<T, U> && cursor<T>;
  298. /// \concept input_cursor
  299. /// \brief The \c input_cursor concept
  300. template<typename T>
  301. CPP_concept input_cursor =
  302. readable_cursor<T> && cursor<T> && has_cursor_next<T>;
  303. /// \concept forward_cursor
  304. /// \brief The \c forward_cursor concept
  305. template<typename T>
  306. CPP_concept forward_cursor =
  307. input_cursor<T> && sentinel_for_cursor<T, T> &&
  308. !range_access::single_pass_t<uncvref_t<T>>::value;
  309. /// \concept bidirectional_cursor_
  310. /// \brief The \c bidirectional_cursor_ concept
  311. template<typename T>
  312. CPP_requires(bidirectional_cursor_,
  313. requires(T & t) //
  314. (
  315. range_access::prev(t)
  316. ));
  317. /// \concept bidirectional_cursor
  318. /// \brief The \c bidirectional_cursor concept
  319. template<typename T>
  320. CPP_concept bidirectional_cursor =
  321. forward_cursor<T> &&
  322. CPP_requires_ref(detail::bidirectional_cursor_, T);
  323. /// \concept random_access_cursor_
  324. /// \brief The \c random_access_cursor_ concept
  325. template<typename T>
  326. CPP_requires(random_access_cursor_,
  327. requires(T & t) //
  328. (
  329. range_access::advance(t, range_access::distance_to(t, t))
  330. ));
  331. /// \concept random_access_cursor
  332. /// \brief The \c random_access_cursor concept
  333. template<typename T>
  334. CPP_concept random_access_cursor =
  335. bidirectional_cursor<T> && //
  336. sized_sentinel_for_cursor<T, T> && //
  337. CPP_requires_ref(detail::random_access_cursor_, T);
  338. template(class T)(
  339. requires std::is_lvalue_reference<T>::value)
  340. void is_lvalue_reference(T&&);
  341. /// \concept contiguous_cursor_
  342. /// \brief The \c contiguous_cursor_ concept
  343. template<typename T>
  344. CPP_requires(contiguous_cursor_,
  345. requires(T & t) //
  346. (
  347. detail::is_lvalue_reference(range_access::read(t))
  348. ));
  349. /// \concept contiguous_cursor
  350. /// \brief The \c contiguous_cursor concept
  351. template<typename T>
  352. CPP_concept contiguous_cursor =
  353. random_access_cursor<T> && //
  354. range_access::contiguous_t<uncvref_t<T>>::value && //
  355. CPP_requires_ref(detail::contiguous_cursor_, T);
  356. // clang-format on
  357. template<typename Cur, bool IsReadable>
  358. RANGES_INLINE_VAR constexpr bool is_writable_cursor_ = true;
  359. template<typename Cur>
  360. RANGES_INLINE_VAR constexpr bool is_writable_cursor_<Cur, true> =
  361. (bool) writable_cursor<Cur, range_access::cursor_value_t<Cur>>;
  362. template<typename Cur>
  363. RANGES_INLINE_VAR constexpr bool is_writable_cursor_v =
  364. is_writable_cursor_<Cur, (bool)readable_cursor<Cur>>;
  365. } // namespace detail
  366. /// \endcond
  367. } // namespace ranges
  368. #include <range/v3/detail/epilogue.hpp>
  369. #endif