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.

394 lines
12KB

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