211 lines · c
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___RANGES_ACCESS_H11#define _LIBCPP___RANGES_ACCESS_H12 13#include <__concepts/class_or_enum.h>14#include <__config>15#include <__cstddef/size_t.h>16#include <__iterator/concepts.h>17#include <__iterator/readable_traits.h>18#include <__ranges/enable_borrowed_range.h>19#include <__type_traits/decay.h>20#include <__type_traits/is_reference.h>21#include <__type_traits/remove_cvref.h>22#include <__type_traits/remove_reference.h>23#include <__utility/auto_cast.h>24#include <__utility/declval.h>25 26#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)27# pragma GCC system_header28#endif29 30_LIBCPP_BEGIN_NAMESPACE_STD31 32#if _LIBCPP_STD_VER >= 2033 34namespace ranges {35template <class _Tp>36concept __can_borrow = is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;37} // namespace ranges38 39// [range.access.begin]40 41namespace ranges {42namespace __begin {43template <class _Tp>44concept __member_begin = __can_borrow<_Tp> && requires(_Tp&& __t) {45 { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;46};47 48void begin() = delete;49 50template <class _Tp>51concept __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 56struct __fn {57 template <class _Tp>58 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept59 requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.60 {61 return __t + 0;62 }63 64 template <class _Tp, size_t _Np>65 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept66 requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.67 {68 return __t + 0;69 }70 71 template <class _Tp>72 requires __member_begin<_Tp>73 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const74 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>80 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const81 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 __begin88 89inline namespace __cpo {90inline constexpr auto begin = __begin::__fn{};91} // namespace __cpo92} // namespace ranges93 94// [range.range]95 96namespace ranges {97template <class _Tp>98using iterator_t = decltype(ranges::begin(std::declval<_Tp&>()));99} // namespace ranges100 101// [range.access.end]102 103namespace ranges {104namespace __end {105template <class _Tp>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 111void end() = delete;112 113template <class _Tp>114concept __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 120struct __fn {121 template <class _Tp, size_t _Np>122 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept123 requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.124 {125 return __t + _Np;126 }127 128 template <class _Tp>129 requires __member_end<_Tp>130 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const131 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>137 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const138 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 __end145 146inline namespace __cpo {147inline constexpr auto end = __end::__fn{};148} // namespace __cpo149} // namespace ranges150 151// [range.access.cbegin]152 153namespace ranges {154namespace __cbegin {155struct __fn {156 template <class _Tp>157 requires is_lvalue_reference_v<_Tp&&>158 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const159 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) const167 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 __cbegin173 174inline namespace __cpo {175inline constexpr auto cbegin = __cbegin::__fn{};176} // namespace __cpo177} // namespace ranges178 179// [range.access.cend]180 181namespace ranges {182namespace __cend {183struct __fn {184 template <class _Tp>185 requires is_lvalue_reference_v<_Tp&&>186 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const187 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 __cend200 201inline namespace __cpo {202inline constexpr auto cend = __cend::__fn{};203} // namespace __cpo204} // namespace ranges205 206#endif // _LIBCPP_STD_VER >= 20207 208_LIBCPP_END_NAMESPACE_STD209 210#endif // _LIBCPP___RANGES_ACCESS_H211