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