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