access.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___RANGES_ACCESS_H
  10. #define _LIBCPP___RANGES_ACCESS_H
  11. #include <__concepts/class_or_enum.h>
  12. #include <__config>
  13. #include <__iterator/concepts.h>
  14. #include <__iterator/readable_traits.h>
  15. #include <__ranges/enable_borrowed_range.h>
  16. #include <__type_traits/decay.h>
  17. #include <__type_traits/is_reference.h>
  18. #include <__type_traits/remove_cvref.h>
  19. #include <__type_traits/remove_reference.h>
  20. #include <__utility/auto_cast.h>
  21. #include <__utility/declval.h>
  22. #include <cstddef>
  23. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  24. # pragma GCC system_header
  25. #endif
  26. _LIBCPP_BEGIN_NAMESPACE_STD
  27. #if _LIBCPP_STD_VER >= 20
  28. namespace ranges {
  29. template <class _Tp>
  30. concept __can_borrow =
  31. is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;
  32. } // namespace ranges
  33. // [range.access.begin]
  34. namespace ranges {
  35. namespace __begin {
  36. template <class _Tp>
  37. concept __member_begin =
  38. __can_borrow<_Tp> &&
  39. __workaround_52970<_Tp> &&
  40. requires(_Tp&& __t) {
  41. { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
  42. };
  43. void begin(auto&) = delete;
  44. void begin(const auto&) = delete;
  45. template <class _Tp>
  46. concept __unqualified_begin =
  47. !__member_begin<_Tp> &&
  48. __can_borrow<_Tp> &&
  49. __class_or_enum<remove_cvref_t<_Tp>> &&
  50. requires(_Tp && __t) {
  51. { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
  52. };
  53. struct __fn {
  54. template <class _Tp>
  55. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept
  56. requires (sizeof(_Tp) >= 0) // Disallow incomplete element types.
  57. {
  58. return __t + 0;
  59. }
  60. template <class _Tp, size_t _Np>
  61. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
  62. requires (sizeof(_Tp) >= 0) // Disallow incomplete element types.
  63. {
  64. return __t + 0;
  65. }
  66. template <class _Tp>
  67. requires __member_begin<_Tp>
  68. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  69. noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin())))
  70. {
  71. return _LIBCPP_AUTO_CAST(__t.begin());
  72. }
  73. template <class _Tp>
  74. requires __unqualified_begin<_Tp>
  75. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  76. noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t))))
  77. {
  78. return _LIBCPP_AUTO_CAST(begin(__t));
  79. }
  80. void operator()(auto&&) const = delete;
  81. };
  82. } // namespace __begin
  83. inline namespace __cpo {
  84. inline constexpr auto begin = __begin::__fn{};
  85. } // namespace __cpo
  86. } // namespace ranges
  87. // [range.range]
  88. namespace ranges {
  89. template <class _Tp>
  90. using iterator_t = decltype(ranges::begin(std::declval<_Tp&>()));
  91. } // namespace ranges
  92. // [range.access.end]
  93. namespace ranges {
  94. namespace __end {
  95. template <class _Tp>
  96. concept __member_end =
  97. __can_borrow<_Tp> &&
  98. __workaround_52970<_Tp> &&
  99. requires(_Tp&& __t) {
  100. typename iterator_t<_Tp>;
  101. { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
  102. };
  103. void end(auto&) = delete;
  104. void end(const auto&) = delete;
  105. template <class _Tp>
  106. concept __unqualified_end =
  107. !__member_end<_Tp> &&
  108. __can_borrow<_Tp> &&
  109. __class_or_enum<remove_cvref_t<_Tp>> &&
  110. requires(_Tp && __t) {
  111. typename iterator_t<_Tp>;
  112. { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>;
  113. };
  114. struct __fn {
  115. template <class _Tp, size_t _Np>
  116. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
  117. requires (sizeof(_Tp) >= 0) // Disallow incomplete element types.
  118. {
  119. return __t + _Np;
  120. }
  121. template <class _Tp>
  122. requires __member_end<_Tp>
  123. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  124. noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end())))
  125. {
  126. return _LIBCPP_AUTO_CAST(__t.end());
  127. }
  128. template <class _Tp>
  129. requires __unqualified_end<_Tp>
  130. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  131. noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t))))
  132. {
  133. return _LIBCPP_AUTO_CAST(end(__t));
  134. }
  135. void operator()(auto&&) const = delete;
  136. };
  137. } // namespace __end
  138. inline namespace __cpo {
  139. inline constexpr auto end = __end::__fn{};
  140. } // namespace __cpo
  141. } // namespace ranges
  142. // [range.access.cbegin]
  143. namespace ranges {
  144. namespace __cbegin {
  145. struct __fn {
  146. template <class _Tp>
  147. requires is_lvalue_reference_v<_Tp&&>
  148. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
  149. constexpr auto operator()(_Tp&& __t) const
  150. noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))))
  151. -> decltype( ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)))
  152. { return ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)); }
  153. template <class _Tp>
  154. requires is_rvalue_reference_v<_Tp&&>
  155. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
  156. constexpr auto operator()(_Tp&& __t) const
  157. noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t))))
  158. -> decltype( ranges::begin(static_cast<const _Tp&&>(__t)))
  159. { return ranges::begin(static_cast<const _Tp&&>(__t)); }
  160. };
  161. } // namespace __cbegin
  162. inline namespace __cpo {
  163. inline constexpr auto cbegin = __cbegin::__fn{};
  164. } // namespace __cpo
  165. } // namespace ranges
  166. // [range.access.cend]
  167. namespace ranges {
  168. namespace __cend {
  169. struct __fn {
  170. template <class _Tp>
  171. requires is_lvalue_reference_v<_Tp&&>
  172. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
  173. constexpr auto operator()(_Tp&& __t) const
  174. noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))))
  175. -> decltype( ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)))
  176. { return ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)); }
  177. template <class _Tp>
  178. requires is_rvalue_reference_v<_Tp&&>
  179. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
  180. constexpr auto operator()(_Tp&& __t) const
  181. noexcept(noexcept(ranges::end(static_cast<const _Tp&&>(__t))))
  182. -> decltype( ranges::end(static_cast<const _Tp&&>(__t)))
  183. { return ranges::end(static_cast<const _Tp&&>(__t)); }
  184. };
  185. } // namespace __cend
  186. inline namespace __cpo {
  187. inline constexpr auto cend = __cend::__fn{};
  188. } // namespace __cpo
  189. } // namespace ranges
  190. #endif // _LIBCPP_STD_VER >= 20
  191. _LIBCPP_END_NAMESPACE_STD
  192. #endif // _LIBCPP___RANGES_ACCESS_H