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