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 > 17 33 34namespace 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 42namespace ranges { 43namespace __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 99inline namespace __cpo { 100 inline constexpr auto begin = __begin::__fn{}; 101} // namespace __cpo 102} // namespace ranges 103 104// [range.range] 105 106namespace ranges { 107 template <class _Tp> 108 using iterator_t = decltype(ranges::begin(std::declval<_Tp&>())); 109} // namespace ranges 110 111// [range.access.end] 112 113namespace ranges { 114namespace __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 165inline namespace __cpo { 166 inline constexpr auto end = __end::__fn{}; 167} // namespace __cpo 168} // namespace ranges 169 170// [range.access.cbegin] 171 172namespace ranges { 173namespace __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 193inline namespace __cpo { 194 inline constexpr auto cbegin = __cbegin::__fn{}; 195} // namespace __cpo 196} // namespace ranges 197 198// [range.access.cend] 199 200namespace ranges { 201namespace __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 221inline namespace __cpo { 222 inline constexpr auto cend = __cend::__fn{}; 223} // namespace __cpo 224} // namespace ranges 225 226#endif // _LIBCPP_STD_VER > 17 227 228_LIBCPP_END_NAMESPACE_STD 229 230#endif // _LIBCPP___RANGES_ACCESS_H 231