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.

720 lines
22KB

  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_RANGE_ACCESS_HPP
  14. #define RANGES_V3_RANGE_ACCESS_HPP
  15. #include <functional> // for reference_wrapper (whose use with begin/end is deprecated)
  16. #include <initializer_list>
  17. #include <iterator>
  18. #include <limits>
  19. #ifdef __has_include
  20. #if __has_include(<string_view>)
  21. #include <string_view>
  22. #endif
  23. #endif
  24. #include <utility>
  25. #include <range/v3/range_fwd.hpp>
  26. #include <range/v3/iterator/concepts.hpp>
  27. #include <range/v3/iterator/reverse_iterator.hpp>
  28. #include <range/v3/iterator/traits.hpp>
  29. #include <range/v3/utility/static_const.hpp>
  30. namespace ranges
  31. {
  32. /// \cond
  33. namespace _begin_
  34. {
  35. // Poison pill for std::begin. (See the detailed discussion at
  36. // https://github.com/ericniebler/stl2/issues/139)
  37. template<typename T>
  38. void begin(T &&) = delete;
  39. #ifdef RANGES_WORKAROUND_MSVC_895622
  40. void begin();
  41. #endif
  42. template<typename T>
  43. void begin(std::initializer_list<T>) = delete;
  44. template<class I>
  45. auto is_iterator(I) -> CPP_ret(void)(requires input_or_output_iterator<I>);
  46. // clang-format off
  47. CPP_def
  48. (
  49. template(typename T)
  50. concept has_member_begin,
  51. requires (T &t)
  52. (
  53. _begin_::is_iterator(t.begin())
  54. ) &&
  55. std::is_lvalue_reference<T>::value
  56. );
  57. CPP_def
  58. (
  59. template(typename T)
  60. concept has_non_member_begin,
  61. requires (T &&t)
  62. (
  63. _begin_::is_iterator(begin((T &&) t))
  64. )
  65. );
  66. // clang-format on
  67. struct fn
  68. {
  69. private:
  70. template<bool>
  71. struct impl_
  72. {
  73. // has_member_begin == true
  74. template<typename R>
  75. constexpr auto operator()(R && r) const noexcept(noexcept(r.begin()))
  76. {
  77. return r.begin();
  78. }
  79. };
  80. template<typename R>
  81. using impl = impl_<has_member_begin<R>>;
  82. #ifdef RANGES_WORKAROUND_GCC_89953
  83. template<typename R>
  84. static constexpr impl<R> impl_v{};
  85. #endif
  86. public:
  87. template<typename R, std::size_t N>
  88. void operator()(R(&&)[N]) const = delete;
  89. template<typename R, std::size_t N>
  90. constexpr R * operator()(R (&array)[N]) const noexcept
  91. {
  92. return array;
  93. }
  94. template<typename R>
  95. #ifdef RANGES_WORKAROUND_GCC_89953
  96. constexpr auto CPP_fun(operator())(R && r)(
  97. const //
  98. noexcept(noexcept(impl_v<R>((R &&) r))) //
  99. requires(has_member_begin<R> || has_non_member_begin<R>))
  100. #else
  101. constexpr auto CPP_fun(operator())(R && r)(
  102. const //
  103. noexcept(noexcept(impl<R>{}((R &&) r))) //
  104. requires(has_member_begin<R> || has_non_member_begin<R>))
  105. #endif
  106. {
  107. return impl<R>{}((R &&) r);
  108. }
  109. #if defined(__cpp_lib_string_view) && __cpp_lib_string_view > 0
  110. template<class CharT, class Traits>
  111. constexpr auto operator()(std::basic_string_view<CharT, Traits> r) const
  112. noexcept
  113. {
  114. return r.begin();
  115. }
  116. #endif
  117. template<typename T, typename Fn = fn>
  118. RANGES_DEPRECATED(
  119. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  120. "instead.")
  121. constexpr auto
  122. operator()(std::reference_wrapper<T> ref) const
  123. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  124. {
  125. return Fn{}(ref.get());
  126. }
  127. template<typename T, typename Fn = fn>
  128. RANGES_DEPRECATED(
  129. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  130. "instead.")
  131. constexpr auto
  132. operator()(ranges::reference_wrapper<T> ref) const
  133. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  134. {
  135. return Fn{}(ref.get());
  136. }
  137. };
  138. // has_member_begin == false
  139. template<>
  140. struct fn::impl_<false>
  141. {
  142. template<typename R>
  143. constexpr auto operator()(R && r) const noexcept(noexcept(begin((R &&) r)))
  144. {
  145. return begin((R &&) r);
  146. }
  147. };
  148. template<typename R>
  149. using _t = decltype(fn{}(std::declval<R>()));
  150. } // namespace _begin_
  151. /// \endcond
  152. /// \ingroup group-range
  153. /// \param r
  154. /// \return \c r, if \c r is an array. Otherwise, `r.begin()` if that expression is
  155. /// well-formed and returns an input_or_output_iterator. Otherwise, `begin(r)` if
  156. /// that expression returns an input_or_output_iterator.
  157. RANGES_DEFINE_CPO(_begin_::fn, begin)
  158. /// \cond
  159. namespace _end_
  160. {
  161. // Poison pill for std::end. (See the detailed discussion at
  162. // https://github.com/ericniebler/stl2/issues/139)
  163. template<typename T>
  164. void end(T &&) = delete;
  165. #ifdef RANGES_WORKAROUND_MSVC_895622
  166. void end();
  167. #endif
  168. template<typename T>
  169. void end(std::initializer_list<T>) = delete;
  170. template<typename I, typename S>
  171. auto is_sentinel(S) -> CPP_ret(void)(requires sentinel_for<S, I>);
  172. // clang-format off
  173. CPP_def
  174. (
  175. template(typename T)
  176. concept has_member_end,
  177. requires (T &t)
  178. (
  179. _end_::is_sentinel<_begin_::_t<T>>(t.end())
  180. ) &&
  181. std::is_lvalue_reference<T>::value
  182. );
  183. CPP_def
  184. (
  185. template(typename T)
  186. concept has_non_member_end,
  187. requires (T &&t)
  188. (
  189. _end_::is_sentinel<_begin_::_t<T>>(end((T &&) t))
  190. )
  191. );
  192. // clang-format on
  193. struct fn
  194. {
  195. private:
  196. template<bool>
  197. struct impl_
  198. {
  199. // has_member_end == true
  200. template<typename R>
  201. constexpr auto operator()(R && r) const noexcept(noexcept(r.end()))
  202. {
  203. return r.end();
  204. }
  205. };
  206. template<typename Int>
  207. using iter_diff_t =
  208. meta::_t<detail::if_then_t<std::is_integral<Int>::value,
  209. std::make_signed<Int>, meta::id<Int>>>;
  210. template<typename R>
  211. using impl = impl_<has_member_end<R>>;
  212. #ifdef RANGES_WORKAROUND_GCC_89953
  213. template<typename R>
  214. static constexpr impl<R> impl_v{};
  215. #endif
  216. public:
  217. template<typename R, std::size_t N>
  218. void operator()(R(&&)[N]) const = delete;
  219. template<typename R, std::size_t N>
  220. constexpr R * operator()(R (&array)[N]) const noexcept
  221. {
  222. return array + N;
  223. }
  224. template<typename R>
  225. #ifdef RANGES_WORKAROUND_GCC_89953
  226. constexpr auto CPP_fun(operator())(R && r)(
  227. const noexcept(noexcept(impl_v<R>((R &&) r))) //
  228. requires(has_member_end<R> || has_non_member_end<R>))
  229. #else
  230. constexpr auto CPP_fun(operator())(R && r)(
  231. const noexcept(noexcept(impl<R>{}((R &&) r))) //
  232. requires(has_member_end<R> || has_non_member_end<R>))
  233. #endif
  234. {
  235. return impl<R>{}((R &&) r);
  236. }
  237. #if defined(__cpp_lib_string_view) && __cpp_lib_string_view > 0
  238. template<class CharT, class Traits>
  239. constexpr auto operator()(std::basic_string_view<CharT, Traits> r) const
  240. noexcept
  241. {
  242. return r.end();
  243. }
  244. #endif
  245. template<typename T, typename Fn = fn>
  246. RANGES_DEPRECATED(
  247. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  248. "instead.")
  249. constexpr auto
  250. operator()(std::reference_wrapper<T> ref) const
  251. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  252. {
  253. return Fn{}(ref.get());
  254. }
  255. template<typename T, typename Fn = fn>
  256. RANGES_DEPRECATED(
  257. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  258. "instead.")
  259. constexpr auto
  260. operator()(ranges::reference_wrapper<T> ref) const
  261. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  262. {
  263. return Fn{}(ref.get());
  264. }
  265. template<typename Int>
  266. auto operator-(Int dist) const
  267. -> CPP_ret(detail::from_end_<iter_diff_t<Int>>)( //
  268. requires detail::integer_like_<Int>)
  269. {
  270. using SInt = iter_diff_t<Int>;
  271. RANGES_EXPECT(0 <= dist);
  272. RANGES_EXPECT(dist <=
  273. static_cast<Int>((std::numeric_limits<SInt>::max)()));
  274. return detail::from_end_<SInt>{-static_cast<SInt>(dist)};
  275. }
  276. };
  277. // has_member_end == false
  278. template<>
  279. struct fn::impl_<false>
  280. {
  281. template<typename R>
  282. constexpr auto operator()(R && r) const noexcept(noexcept(end((R &&) r)))
  283. {
  284. return end((R &&) r);
  285. }
  286. };
  287. template<typename R>
  288. using _t = decltype(fn{}(std::declval<R>()));
  289. } // namespace _end_
  290. /// \endcond
  291. /// \ingroup group-range
  292. /// \param r
  293. /// \return \c r+size(r), if \c r is an array. Otherwise, `r.end()` if that expression
  294. /// is
  295. /// well-formed and returns an input_or_output_iterator. Otherwise, `end(r)` if that
  296. /// expression returns an input_or_output_iterator.
  297. RANGES_DEFINE_CPO(_end_::fn, end)
  298. /// \cond
  299. namespace _cbegin_
  300. {
  301. struct fn
  302. {
  303. template<typename R>
  304. constexpr _begin_::_t<detail::as_const_t<R>> operator()(R && r) const
  305. noexcept(noexcept(ranges::begin(detail::as_const((R &&) r))))
  306. {
  307. return ranges::begin(detail::as_const((R &&) r));
  308. }
  309. };
  310. } // namespace _cbegin_
  311. /// \endcond
  312. /// \ingroup group-range
  313. /// \param r
  314. /// \return The result of calling `ranges::begin` with a const-qualified
  315. /// reference to r.
  316. RANGES_INLINE_VARIABLE(_cbegin_::fn, cbegin)
  317. /// \cond
  318. namespace _cend_
  319. {
  320. struct fn
  321. {
  322. template<typename R>
  323. constexpr _end_::_t<detail::as_const_t<R>> operator()(R && r) const
  324. noexcept(noexcept(ranges::end(detail::as_const((R &&) r))))
  325. {
  326. return ranges::end(detail::as_const((R &&) r));
  327. }
  328. };
  329. } // namespace _cend_
  330. /// \endcond
  331. /// \ingroup group-range
  332. /// \param r
  333. /// \return The result of calling `ranges::end` with a const-qualified
  334. /// reference to r.
  335. RANGES_INLINE_VARIABLE(_cend_::fn, cend)
  336. /// \cond
  337. namespace _rbegin_
  338. {
  339. template<typename R>
  340. void rbegin(R &&) = delete;
  341. // Non-standard, to keep unqualified rbegin(r) from finding std::rbegin
  342. // and returning a std::reverse_iterator.
  343. template<typename T>
  344. void rbegin(std::initializer_list<T>) = delete;
  345. template<typename T, std::size_t N>
  346. void rbegin(T (&)[N]) = delete;
  347. // clang-format off
  348. CPP_def
  349. (
  350. template(typename T)
  351. concept has_member_rbegin,
  352. requires (T &t)
  353. (
  354. _begin_::is_iterator(t.rbegin())
  355. ) &&
  356. std::is_lvalue_reference<T>::value
  357. );
  358. CPP_def
  359. (
  360. template(typename T)
  361. concept has_non_member_rbegin,
  362. requires (T &&t)
  363. (
  364. _begin_::is_iterator(rbegin((T &&) t))
  365. )
  366. );
  367. CPP_def
  368. (
  369. template(typename T)
  370. concept can_reverse_end,
  371. requires (T &&t)
  372. (
  373. // make_reverse_iterator is constrained with
  374. // bidirectional_iterator.
  375. ranges::make_reverse_iterator(ranges::end((T &&) t))
  376. ) &&
  377. same_as<_begin_::_t<T>, _end_::_t<T>>
  378. );
  379. // clang-format on
  380. struct fn
  381. {
  382. private:
  383. // has_member_rbegin == true
  384. template<int>
  385. struct impl_
  386. {
  387. template<typename R>
  388. constexpr auto operator()(R && r) const noexcept(noexcept(r.rbegin()))
  389. {
  390. return r.rbegin();
  391. }
  392. };
  393. template<typename R>
  394. using impl =
  395. impl_<has_member_rbegin<R> ? 0 : has_non_member_rbegin<R> ? 1 : 2>;
  396. public:
  397. template<typename R>
  398. constexpr auto CPP_fun(operator())(R && r)(
  399. const noexcept(noexcept(impl<R>{}((R &&) r))) //
  400. requires(has_member_rbegin<R> || has_non_member_rbegin<R> ||
  401. can_reverse_end<R>))
  402. {
  403. return impl<R>{}((R &&) r);
  404. }
  405. template<typename T, typename Fn = fn>
  406. RANGES_DEPRECATED(
  407. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  408. "instead.")
  409. constexpr auto
  410. operator()(std::reference_wrapper<T> ref) const
  411. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  412. {
  413. return Fn{}(ref.get());
  414. }
  415. template<typename T, typename Fn = fn>
  416. RANGES_DEPRECATED(
  417. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  418. "instead.")
  419. constexpr auto
  420. operator()(ranges::reference_wrapper<T> ref) const
  421. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  422. {
  423. return Fn{}(ref.get());
  424. }
  425. };
  426. // has_non_member_rbegin == true
  427. template<>
  428. struct fn::impl_<1>
  429. {
  430. template<typename R>
  431. constexpr auto operator()(R && r) const noexcept(noexcept(rbegin((R &&) r)))
  432. {
  433. return rbegin((R &&) r);
  434. }
  435. };
  436. // can_reverse_end
  437. template<>
  438. struct fn::impl_<2>
  439. {
  440. template<typename R>
  441. constexpr auto operator()(R && r) const
  442. noexcept(noexcept(ranges::make_reverse_iterator(ranges::end((R &&) r))))
  443. {
  444. return ranges::make_reverse_iterator(ranges::end((R &&) r));
  445. }
  446. };
  447. template<typename R>
  448. using _t = decltype(fn{}(std::declval<R>()));
  449. } // namespace _rbegin_
  450. /// \endcond
  451. /// \ingroup group-range
  452. /// \param r
  453. /// \return `make_reverse_iterator(r+size(r))` if r is an array. Otherwise,
  454. /// `r.rbegin()` if that expression is well-formed and returns an
  455. /// input_or_output_iterator. Otherwise, `make_reverse_iterator(ranges::end(r))` if
  456. /// `ranges::begin(r)` and `ranges::end(r)` are both well-formed and have the same
  457. /// type that satisfies bidirectional_iterator.
  458. RANGES_DEFINE_CPO(_rbegin_::fn, rbegin)
  459. /// \cond
  460. namespace _rend_
  461. {
  462. template<typename R>
  463. void rend(R &&) = delete;
  464. // Non-standard, to keep unqualified rend(r) from finding std::rend
  465. // and returning a std::reverse_iterator.
  466. template<typename T>
  467. void rend(std::initializer_list<T>) = delete;
  468. template<typename T, std::size_t N>
  469. void rend(T (&)[N]) = delete;
  470. // clang-format off
  471. CPP_def
  472. (
  473. template(typename T)
  474. concept has_member_rend,
  475. requires (T &t)
  476. (
  477. _end_::is_sentinel<_rbegin_::_t<T &>>(t.rend())
  478. ) &&
  479. std::is_lvalue_reference<T>::value
  480. );
  481. CPP_def
  482. (
  483. template(typename T)
  484. concept has_non_member_rend,
  485. requires (T &&t)
  486. (
  487. _end_::is_sentinel<_rbegin_::_t<T &>>(rend((T &&) t))
  488. )
  489. );
  490. CPP_def
  491. (
  492. template(typename T)
  493. concept can_reverse_begin,
  494. requires (T &&t)
  495. (
  496. // make_reverse_iterator is constrained with
  497. // bidirectional_iterator.
  498. ranges::make_reverse_iterator(ranges::begin((T &&) t))
  499. ) &&
  500. same_as<_begin_::_t<T>, _end_::_t<T>>
  501. );
  502. // clang-format on
  503. struct fn
  504. {
  505. private:
  506. // has_member_rbegin == true
  507. template<int>
  508. struct impl_
  509. {
  510. template<typename R>
  511. constexpr auto operator()(R && r) const noexcept(noexcept(r.rend()))
  512. {
  513. return r.rend();
  514. }
  515. };
  516. template<typename R>
  517. using impl = impl_<has_member_rend<R> ? 0 : has_non_member_rend<R> ? 1 : 2>;
  518. public:
  519. template<typename R>
  520. constexpr auto CPP_fun(operator())(R && r)(
  521. const noexcept(noexcept(impl<R>{}((R &&) r))) //
  522. requires(has_member_rend<R> || has_non_member_rend<R> ||
  523. can_reverse_begin<R>))
  524. {
  525. return impl<R>{}((R &&) r);
  526. }
  527. template<typename T, typename Fn = fn>
  528. RANGES_DEPRECATED(
  529. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  530. "instead.")
  531. constexpr auto
  532. operator()(std::reference_wrapper<T> ref) const
  533. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  534. {
  535. return Fn{}(ref.get());
  536. }
  537. template<typename T, typename Fn = fn>
  538. RANGES_DEPRECATED(
  539. "Using a reference_wrapper as a Range is deprecated. Use views::ref "
  540. "instead.")
  541. constexpr auto
  542. operator()(ranges::reference_wrapper<T> ref) const
  543. noexcept(noexcept(Fn{}(ref.get()))) -> decltype(Fn{}(ref.get()))
  544. {
  545. return Fn{}(ref.get());
  546. }
  547. };
  548. // has_non_member_rend == true
  549. template<>
  550. struct fn::impl_<1>
  551. {
  552. template<typename R>
  553. constexpr auto operator()(R && r) const noexcept(noexcept(rend((R &&) r)))
  554. {
  555. return rend((R &&) r);
  556. }
  557. };
  558. // can_reverse_begin
  559. template<>
  560. struct fn::impl_<2>
  561. {
  562. template<typename R>
  563. constexpr auto operator()(R && r) const
  564. noexcept(noexcept(ranges::make_reverse_iterator(ranges::begin((R &&) r))))
  565. {
  566. return ranges::make_reverse_iterator(ranges::begin((R &&) r));
  567. }
  568. };
  569. template<typename R>
  570. using _t = decltype(fn{}(std::declval<R>()));
  571. } // namespace _rend_
  572. /// \endcond
  573. /// \ingroup group-range
  574. /// \param r
  575. /// \return `make_reverse_iterator(r))` if r is an array. Otherwise,
  576. /// `r.rend()` if that expression is well-formed and returns a type that
  577. /// satisfies `sentinel_for<S, I>` where `I` is the type of `ranges::rbegin(r)`.
  578. /// Otherwise, `make_reverse_iterator(ranges::begin(r))` if `ranges::begin(r)`
  579. /// and `ranges::end(r)` are both well-formed and have the same type that
  580. /// satisfies bidirectional_iterator.
  581. RANGES_DEFINE_CPO(_rend_::fn, rend)
  582. /// \cond
  583. namespace _crbegin_
  584. {
  585. struct fn
  586. {
  587. template<typename R>
  588. constexpr _rbegin_::_t<detail::as_const_t<R>> operator()(R && r) const
  589. noexcept(noexcept(ranges::rbegin(detail::as_const((R &&) r))))
  590. {
  591. return ranges::rbegin(detail::as_const((R &&) r));
  592. }
  593. };
  594. } // namespace _crbegin_
  595. /// \endcond
  596. /// \ingroup group-range
  597. /// \param r
  598. /// \return The result of calling `ranges::rbegin` with a const-qualified
  599. /// reference to r.
  600. RANGES_INLINE_VARIABLE(_crbegin_::fn, crbegin)
  601. /// \cond
  602. namespace _crend_
  603. {
  604. struct fn
  605. {
  606. template<typename R>
  607. constexpr _rend_::_t<detail::as_const_t<R>> operator()(R && r) const
  608. noexcept(noexcept(ranges::rend(detail::as_const((R &&) r))))
  609. {
  610. return ranges::rend(detail::as_const((R &&) r));
  611. }
  612. };
  613. } // namespace _crend_
  614. /// \endcond
  615. /// \ingroup group-range
  616. /// \param r
  617. /// \return The result of calling `ranges::rend` with a const-qualified
  618. /// reference to r.
  619. RANGES_INLINE_VARIABLE(_crend_::fn, crend)
  620. template<typename Rng>
  621. using iterator_t = decltype(begin(std::declval<Rng &>()));
  622. template<typename Rng>
  623. using sentinel_t = decltype(end(std::declval<Rng &>()));
  624. namespace cpp20
  625. {
  626. using ranges::begin;
  627. using ranges::cbegin;
  628. using ranges::cend;
  629. using ranges::crbegin;
  630. using ranges::crend;
  631. using ranges::end;
  632. using ranges::rbegin;
  633. using ranges::rend;
  634. using ranges::iterator_t;
  635. using ranges::sentinel_t;
  636. } // namespace cpp20
  637. } // namespace ranges
  638. #endif