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