access.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 = is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;
  31. } // namespace ranges
  32. // [range.access.begin]
  33. namespace ranges {
  34. namespace __begin {
  35. template <class _Tp>
  36. concept __member_begin = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) {
  37. { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
  38. };
  39. void begin(auto&) = delete;
  40. void begin(const auto&) = delete;
  41. template <class _Tp>
  42. concept __unqualified_begin =
  43. !__member_begin<_Tp> && __can_borrow<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
  44. { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
  45. };
  46. struct __fn {
  47. template <class _Tp>
  48. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept
  49. requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.
  50. {
  51. return __t + 0;
  52. }
  53. template <class _Tp, size_t _Np>
  54. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
  55. requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.
  56. {
  57. return __t + 0;
  58. }
  59. template <class _Tp>
  60. requires __member_begin<_Tp>
  61. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  62. noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin()))) {
  63. return _LIBCPP_AUTO_CAST(__t.begin());
  64. }
  65. template <class _Tp>
  66. requires __unqualified_begin<_Tp>
  67. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  68. noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t)))) {
  69. return _LIBCPP_AUTO_CAST(begin(__t));
  70. }
  71. void operator()(auto&&) const = delete;
  72. };
  73. } // namespace __begin
  74. inline namespace __cpo {
  75. inline constexpr auto begin = __begin::__fn{};
  76. } // namespace __cpo
  77. } // namespace ranges
  78. // [range.range]
  79. namespace ranges {
  80. template <class _Tp>
  81. using iterator_t = decltype(ranges::begin(std::declval<_Tp&>()));
  82. } // namespace ranges
  83. // [range.access.end]
  84. namespace ranges {
  85. namespace __end {
  86. template <class _Tp>
  87. concept __member_end = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) {
  88. typename iterator_t<_Tp>;
  89. { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
  90. };
  91. void end(auto&) = delete;
  92. void end(const auto&) = delete;
  93. template <class _Tp>
  94. concept __unqualified_end =
  95. !__member_end<_Tp> && __can_borrow<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
  96. typename iterator_t<_Tp>;
  97. { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>;
  98. };
  99. struct __fn {
  100. template <class _Tp, size_t _Np>
  101. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
  102. requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.
  103. {
  104. return __t + _Np;
  105. }
  106. template <class _Tp>
  107. requires __member_end<_Tp>
  108. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  109. noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end()))) {
  110. return _LIBCPP_AUTO_CAST(__t.end());
  111. }
  112. template <class _Tp>
  113. requires __unqualified_end<_Tp>
  114. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  115. noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t)))) {
  116. return _LIBCPP_AUTO_CAST(end(__t));
  117. }
  118. void operator()(auto&&) const = delete;
  119. };
  120. } // namespace __end
  121. inline namespace __cpo {
  122. inline constexpr auto end = __end::__fn{};
  123. } // namespace __cpo
  124. } // namespace ranges
  125. // [range.access.cbegin]
  126. namespace ranges {
  127. namespace __cbegin {
  128. struct __fn {
  129. template <class _Tp>
  130. requires is_lvalue_reference_v<_Tp&&>
  131. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  132. noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))))
  133. -> decltype(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))) {
  134. return ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t));
  135. }
  136. template <class _Tp>
  137. requires is_rvalue_reference_v<_Tp&&>
  138. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  139. noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t))))
  140. -> decltype(ranges::begin(static_cast<const _Tp&&>(__t))) {
  141. return ranges::begin(static_cast<const _Tp&&>(__t));
  142. }
  143. };
  144. } // namespace __cbegin
  145. inline namespace __cpo {
  146. inline constexpr auto cbegin = __cbegin::__fn{};
  147. } // namespace __cpo
  148. } // namespace ranges
  149. // [range.access.cend]
  150. namespace ranges {
  151. namespace __cend {
  152. struct __fn {
  153. template <class _Tp>
  154. requires is_lvalue_reference_v<_Tp&&>
  155. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  156. noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))))
  157. -> decltype(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))) {
  158. return ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t));
  159. }
  160. template <class _Tp>
  161. requires is_rvalue_reference_v<_Tp&&>
  162. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
  163. noexcept(noexcept(ranges::end(static_cast<const _Tp&&>(__t))))
  164. -> decltype(ranges::end(static_cast<const _Tp&&>(__t))) {
  165. return ranges::end(static_cast<const _Tp&&>(__t));
  166. }
  167. };
  168. } // namespace __cend
  169. inline namespace __cpo {
  170. inline constexpr auto cend = __cend::__fn{};
  171. } // namespace __cpo
  172. } // namespace ranges
  173. #endif // _LIBCPP_STD_VER >= 20
  174. _LIBCPP_END_NAMESPACE_STD
  175. #endif // _LIBCPP___RANGES_ACCESS_H