xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/access.h (revision 38a52bd3b5cac3da6f7f6eef3dd050e6aa08ebb3)
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 #ifndef _LIBCPP___RANGES_ACCESS_H
10 #define _LIBCPP___RANGES_ACCESS_H
11 
12 #include <__concepts/class_or_enum.h>
13 #include <__config>
14 #include <__iterator/concepts.h>
15 #include <__iterator/readable_traits.h>
16 #include <__ranges/enable_borrowed_range.h>
17 #include <__utility/as_const.h>
18 #include <__utility/auto_cast.h>
19 #include <concepts>
20 #include <type_traits>
21 
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 #pragma GCC system_header
24 #endif
25 
26 _LIBCPP_BEGIN_NAMESPACE_STD
27 
28 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
29 
30 namespace ranges {
31   template <class _Tp>
32   concept __can_borrow =
33     is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;
34 } // namespace ranges
35 
36 // [range.access.begin]
37 
38 namespace ranges {
39 namespace __begin {
40   template <class _Tp>
41   concept __member_begin =
42     __can_borrow<_Tp> &&
43     __workaround_52970<_Tp> &&
44     requires(_Tp&& __t) {
45       { _LIBCPP_AUTO_CAST(__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       { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
58     };
59 
60   struct __fn {
61     template <class _Tp>
62     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept
63       requires (sizeof(_Tp) != 0)  // Disallow incomplete element types.
64     {
65       return __t + 0;
66     }
67 
68     template <class _Tp, size_t _Np>
69     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
70       requires (sizeof(_Tp) != 0)  // Disallow incomplete element types.
71     {
72       return __t + 0;
73     }
74 
75     template <class _Tp>
76       requires __member_begin<_Tp>
77     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
78       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin())))
79     {
80       return _LIBCPP_AUTO_CAST(__t.begin());
81     }
82 
83     template <class _Tp>
84       requires __unqualified_begin<_Tp>
85     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
86       noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t))))
87     {
88       return _LIBCPP_AUTO_CAST(begin(__t));
89     }
90 
91     void operator()(auto&&) const = delete;
92   };
93 } // namespace __begin
94 
95 inline namespace __cpo {
96   inline constexpr auto begin = __begin::__fn{};
97 } // namespace __cpo
98 } // namespace ranges
99 
100 // [range.range]
101 
102 namespace ranges {
103   template <class _Tp>
104   using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
105 } // namespace ranges
106 
107 // [range.access.end]
108 
109 namespace ranges {
110 namespace __end {
111   template <class _Tp>
112   concept __member_end =
113     __can_borrow<_Tp> &&
114     __workaround_52970<_Tp> &&
115     requires(_Tp&& __t) {
116       typename iterator_t<_Tp>;
117       { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
118     };
119 
120   void end(auto&) = delete;
121   void end(const auto&) = delete;
122 
123   template <class _Tp>
124   concept __unqualified_end =
125     !__member_end<_Tp> &&
126     __can_borrow<_Tp> &&
127     __class_or_enum<remove_cvref_t<_Tp>> &&
128     requires(_Tp && __t) {
129       typename iterator_t<_Tp>;
130       { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>;
131     };
132 
133   class __fn {
134   public:
135     template <class _Tp, size_t _Np>
136     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
137       requires (sizeof(_Tp) != 0)  // Disallow incomplete element types.
138     {
139       return __t + _Np;
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(_LIBCPP_AUTO_CAST(__t.end())))
146     {
147       return _LIBCPP_AUTO_CAST(__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(_LIBCPP_AUTO_CAST(end(__t))))
154     {
155       return _LIBCPP_AUTO_CAST(end(__t));
156     }
157 
158     void operator()(auto&&) const = delete;
159   };
160 } // namespace __end
161 
162 inline namespace __cpo {
163   inline constexpr auto end = __end::__fn{};
164 } // namespace __cpo
165 } // namespace ranges
166 
167 // [range.access.cbegin]
168 
169 namespace ranges {
170 namespace __cbegin {
171   struct __fn {
172     template <class _Tp>
173       requires is_lvalue_reference_v<_Tp&&>
174     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
175     constexpr auto operator()(_Tp&& __t) const
176       noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))))
177       -> decltype(      ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)))
178       { return          ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)); }
179 
180     template <class _Tp>
181       requires is_rvalue_reference_v<_Tp&&>
182     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
183     constexpr auto operator()(_Tp&& __t) const
184       noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t))))
185       -> decltype(      ranges::begin(static_cast<const _Tp&&>(__t)))
186       { return          ranges::begin(static_cast<const _Tp&&>(__t)); }
187   };
188 } // namespace __cbegin
189 
190 inline namespace __cpo {
191   inline constexpr auto cbegin = __cbegin::__fn{};
192 } // namespace __cpo
193 } // namespace ranges
194 
195 // [range.access.cend]
196 
197 namespace ranges {
198 namespace __cend {
199   struct __fn {
200     template <class _Tp>
201       requires is_lvalue_reference_v<_Tp&&>
202     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
203     constexpr auto operator()(_Tp&& __t) const
204       noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))))
205       -> decltype(      ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)))
206       { return          ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)); }
207 
208     template <class _Tp>
209       requires is_rvalue_reference_v<_Tp&&>
210     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
211     constexpr auto operator()(_Tp&& __t) const
212       noexcept(noexcept(ranges::end(static_cast<const _Tp&&>(__t))))
213       -> decltype(      ranges::end(static_cast<const _Tp&&>(__t)))
214       { return          ranges::end(static_cast<const _Tp&&>(__t)); }
215   };
216 } // namespace __cend
217 
218 inline namespace __cpo {
219   inline constexpr auto cend = __cend::__fn{};
220 } // namespace __cpo
221 } // namespace ranges
222 
223 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
224 
225 _LIBCPP_END_NAMESPACE_STD
226 
227 #endif // _LIBCPP___RANGES_ACCESS_H
228