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 12 #include <__concepts/class_or_enum.h> 13 #include <__config> 14 #include <__iterator/concepts.h> 15 #include <__iterator/readable_traits.h> 16 #include <__ranges/enable_borrowed_range.h> 17 #include <__utility/as_const.h> 18 #include <__utility/auto_cast.h> 19 #include <concepts> 20 #include <type_traits> 21 22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23 #pragma GCC system_header 24 #endif 25 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) 29 30 namespace ranges { 31 template <class _Tp> 32 concept __can_borrow = 33 is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>; 34 } // namespace ranges 35 36 // [range.access.begin] 37 38 namespace ranges { 39 namespace __begin { 40 template <class _Tp> 41 concept __member_begin = 42 __can_borrow<_Tp> && 43 __workaround_52970<_Tp> && 44 requires(_Tp&& __t) { 45 { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator; 46 }; 47 48 void begin(auto&) = delete; 49 void begin(const auto&) = delete; 50 51 template <class _Tp> 52 concept __unqualified_begin = 53 !__member_begin<_Tp> && 54 __can_borrow<_Tp> && 55 __class_or_enum<remove_cvref_t<_Tp>> && 56 requires(_Tp && __t) { 57 { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator; 58 }; 59 60 struct __fn { 61 template <class _Tp> 62 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept 63 requires (sizeof(_Tp) != 0) // Disallow incomplete element types. 64 { 65 return __t + 0; 66 } 67 68 template <class _Tp, size_t _Np> 69 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept 70 requires (sizeof(_Tp) != 0) // Disallow incomplete element types. 71 { 72 return __t + 0; 73 } 74 75 template <class _Tp> 76 requires __member_begin<_Tp> 77 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 78 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin()))) 79 { 80 return _LIBCPP_AUTO_CAST(__t.begin()); 81 } 82 83 template <class _Tp> 84 requires __unqualified_begin<_Tp> 85 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 86 noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t)))) 87 { 88 return _LIBCPP_AUTO_CAST(begin(__t)); 89 } 90 91 void operator()(auto&&) const = delete; 92 }; 93 } // namespace __begin 94 95 inline namespace __cpo { 96 inline constexpr auto begin = __begin::__fn{}; 97 } // namespace __cpo 98 } // namespace ranges 99 100 // [range.range] 101 102 namespace ranges { 103 template <class _Tp> 104 using iterator_t = decltype(ranges::begin(declval<_Tp&>())); 105 } // namespace ranges 106 107 // [range.access.end] 108 109 namespace ranges { 110 namespace __end { 111 template <class _Tp> 112 concept __member_end = 113 __can_borrow<_Tp> && 114 __workaround_52970<_Tp> && 115 requires(_Tp&& __t) { 116 typename iterator_t<_Tp>; 117 { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>; 118 }; 119 120 void end(auto&) = delete; 121 void end(const auto&) = delete; 122 123 template <class _Tp> 124 concept __unqualified_end = 125 !__member_end<_Tp> && 126 __can_borrow<_Tp> && 127 __class_or_enum<remove_cvref_t<_Tp>> && 128 requires(_Tp && __t) { 129 typename iterator_t<_Tp>; 130 { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>; 131 }; 132 133 class __fn { 134 public: 135 template <class _Tp, size_t _Np> 136 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept 137 requires (sizeof(_Tp) != 0) // Disallow incomplete element types. 138 { 139 return __t + _Np; 140 } 141 142 template <class _Tp> 143 requires __member_end<_Tp> 144 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 145 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end()))) 146 { 147 return _LIBCPP_AUTO_CAST(__t.end()); 148 } 149 150 template <class _Tp> 151 requires __unqualified_end<_Tp> 152 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 153 noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t)))) 154 { 155 return _LIBCPP_AUTO_CAST(end(__t)); 156 } 157 158 void operator()(auto&&) const = delete; 159 }; 160 } // namespace __end 161 162 inline namespace __cpo { 163 inline constexpr auto end = __end::__fn{}; 164 } // namespace __cpo 165 } // namespace ranges 166 167 // [range.access.cbegin] 168 169 namespace ranges { 170 namespace __cbegin { 171 struct __fn { 172 template <class _Tp> 173 requires is_lvalue_reference_v<_Tp&&> 174 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 175 constexpr auto operator()(_Tp&& __t) const 176 noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)))) 177 -> decltype( ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))) 178 { return ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)); } 179 180 template <class _Tp> 181 requires is_rvalue_reference_v<_Tp&&> 182 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 183 constexpr auto operator()(_Tp&& __t) const 184 noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t)))) 185 -> decltype( ranges::begin(static_cast<const _Tp&&>(__t))) 186 { return ranges::begin(static_cast<const _Tp&&>(__t)); } 187 }; 188 } // namespace __cbegin 189 190 inline namespace __cpo { 191 inline constexpr auto cbegin = __cbegin::__fn{}; 192 } // namespace __cpo 193 } // namespace ranges 194 195 // [range.access.cend] 196 197 namespace ranges { 198 namespace __cend { 199 struct __fn { 200 template <class _Tp> 201 requires is_lvalue_reference_v<_Tp&&> 202 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 203 constexpr auto operator()(_Tp&& __t) const 204 noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)))) 205 -> decltype( ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))) 206 { return ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)); } 207 208 template <class _Tp> 209 requires is_rvalue_reference_v<_Tp&&> 210 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 211 constexpr auto operator()(_Tp&& __t) const 212 noexcept(noexcept(ranges::end(static_cast<const _Tp&&>(__t)))) 213 -> decltype( ranges::end(static_cast<const _Tp&&>(__t))) 214 { return ranges::end(static_cast<const _Tp&&>(__t)); } 215 }; 216 } // namespace __cend 217 218 inline namespace __cpo { 219 inline constexpr auto cend = __cend::__fn{}; 220 } // namespace __cpo 221 } // namespace ranges 222 223 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 224 225 _LIBCPP_END_NAMESPACE_STD 226 227 #endif // _LIBCPP___RANGES_ACCESS_H 228