1 // -*- C++ -*- 2 //===------------------------ __ranges/access.h ---------------------------===// 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 <__config> 13 #include <__iterator/concepts.h> 14 #include <__iterator/readable_traits.h> 15 #include <__ranges/enable_borrowed_range.h> 16 #include <__utility/__decay_copy.h> 17 #include <__utility/forward.h> 18 #include <concepts> 19 #include <type_traits> 20 21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22 #pragma GCC system_header 23 #endif 24 25 _LIBCPP_PUSH_MACROS 26 #include <__undef_macros> 27 28 _LIBCPP_BEGIN_NAMESPACE_STD 29 30 #if !defined(_LIBCPP_HAS_NO_RANGES) 31 32 // clang-format off 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 39 template<class _Tp> 40 concept __is_complete = requires { sizeof(_Tp); }; 41 } // namespace ranges 42 43 // [range.access.begin] 44 namespace ranges::__begin { 45 template <class _Tp> 46 concept __member_begin = 47 __can_borrow<_Tp> && 48 requires(_Tp&& __t) { 49 { _VSTD::__decay_copy(__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 { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator; 62 }; 63 64 struct __fn { 65 template <class _Tp> 66 requires is_array_v<remove_cv_t<_Tp>> 67 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const noexcept { 68 constexpr bool __complete = __is_complete<iter_value_t<_Tp> >; 69 if constexpr (__complete) { // used to disable cryptic diagnostic 70 return __t + 0; 71 } 72 else { 73 static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."); 74 } 75 } 76 77 template <class _Tp> 78 requires __member_begin<_Tp> 79 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 80 noexcept(noexcept(_VSTD::__decay_copy(__t.begin()))) 81 { 82 return __t.begin(); 83 } 84 85 template <class _Tp> 86 requires __unqualified_begin<_Tp> 87 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 88 noexcept(noexcept(_VSTD::__decay_copy(begin(__t)))) 89 { 90 return begin(__t); 91 } 92 93 void operator()(auto&&) const = delete; 94 }; 95 } // namespace ranges::__begin 96 97 namespace ranges { 98 inline namespace __cpo { 99 inline constexpr auto begin = __begin::__fn{}; 100 } // namespace __cpo 101 102 template <class _Tp> 103 using iterator_t = decltype(ranges::begin(declval<_Tp&>())); 104 } // namespace ranges 105 106 // [range.access.end] 107 namespace ranges::__end { 108 template <class _Tp> 109 concept __member_end = 110 __can_borrow<_Tp> && 111 requires(_Tp&& __t) { 112 typename iterator_t<_Tp>; 113 { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >; 114 }; 115 116 void end(auto&) = delete; 117 void end(const auto&) = delete; 118 119 template <class _Tp> 120 concept __unqualified_end = 121 !__member_end<_Tp> && 122 __can_borrow<_Tp> && 123 __class_or_enum<remove_cvref_t<_Tp> > && 124 requires(_Tp && __t) { 125 typename iterator_t<_Tp>; 126 { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >; 127 }; 128 129 class __fn { 130 public: 131 template <class _Tp, size_t _Np> 132 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept { 133 constexpr bool __complete = __is_complete<remove_cv_t<_Tp> >; 134 if constexpr (__complete) { // used to disable cryptic diagnostic 135 return __t + _Np; 136 } 137 else { 138 static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."); 139 } 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(_VSTD::__decay_copy(__t.end()))) 146 { 147 return _VSTD::forward<_Tp>(__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(_VSTD::__decay_copy(end(__t)))) 154 { 155 return end(__t); 156 } 157 158 void operator()(auto&&) const = delete; 159 }; 160 } // namespace ranges::__end 161 162 namespace ranges::inline __cpo { 163 inline constexpr auto end = __end::__fn{}; 164 } // namespace ranges::__cpo 165 166 namespace ranges::__cbegin { 167 struct __fn { 168 template <class _Tp> 169 requires invocable<decltype(ranges::begin), _Tp const&> 170 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const 171 noexcept(noexcept(ranges::begin(_VSTD::as_const(__t)))) 172 { 173 return ranges::begin(_VSTD::as_const(__t)); 174 } 175 176 template <class _Tp> 177 requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::begin), _Tp const&&> 178 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 179 noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t)))) 180 { 181 return ranges::begin(static_cast<_Tp const&&>(__t)); 182 } 183 }; 184 } // namespace ranges::__cbegin 185 186 namespace ranges::inline __cpo { 187 inline constexpr auto cbegin = __cbegin::__fn{}; 188 } // namespace ranges::__cpo 189 190 namespace ranges::__cend { 191 struct __fn { 192 template <class _Tp> 193 requires invocable<decltype(ranges::end), _Tp const&> 194 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const 195 noexcept(noexcept(ranges::end(_VSTD::as_const(__t)))) 196 { 197 return ranges::end(_VSTD::as_const(__t)); 198 } 199 200 template <class _Tp> 201 requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::end), _Tp const&&> 202 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 203 noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t)))) 204 { 205 return ranges::end(static_cast<_Tp const&&>(__t)); 206 } 207 }; 208 } // namespace ranges::__cend 209 210 namespace ranges::inline __cpo { 211 inline constexpr auto cend = __cend::__fn{}; 212 } // namespace ranges::__cpo 213 214 // clang-format off 215 216 #endif // !defined(_LIBCPP_HAS_NO_RANGES) 217 218 _LIBCPP_END_NAMESPACE_STD 219 220 _LIBCPP_POP_MACROS 221 222 #endif // _LIBCPP___RANGES_ACCESS_H 223