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___ITERATOR_CONCEPTS_H |
11 | #define _LIBCPP___ITERATOR_CONCEPTS_H |
12 | |
13 | #include <__concepts/arithmetic.h> |
14 | #include <__concepts/assignable.h> |
15 | #include <__concepts/common_reference_with.h> |
16 | #include <__concepts/constructible.h> |
17 | #include <__concepts/copyable.h> |
18 | #include <__concepts/derived_from.h> |
19 | #include <__concepts/equality_comparable.h> |
20 | #include <__concepts/invocable.h> |
21 | #include <__concepts/movable.h> |
22 | #include <__concepts/predicate.h> |
23 | #include <__concepts/regular.h> |
24 | #include <__concepts/relation.h> |
25 | #include <__concepts/same_as.h> |
26 | #include <__concepts/semiregular.h> |
27 | #include <__concepts/totally_ordered.h> |
28 | #include <__config> |
29 | #include <__iterator/incrementable_traits.h> |
30 | #include <__iterator/iter_move.h> |
31 | #include <__iterator/iterator_traits.h> |
32 | #include <__memory/pointer_traits.h> |
33 | #include <__type_traits/add_pointer.h> |
34 | #include <__type_traits/common_reference.h> |
35 | #include <__type_traits/conditional.h> |
36 | #include <__type_traits/disjunction.h> |
37 | #include <__type_traits/enable_if.h> |
38 | #include <__type_traits/integral_constant.h> |
39 | #include <__type_traits/invoke.h> |
40 | #include <__type_traits/is_pointer.h> |
41 | #include <__type_traits/is_primary_template.h> |
42 | #include <__type_traits/is_reference.h> |
43 | #include <__type_traits/is_referenceable.h> |
44 | #include <__type_traits/is_valid_expansion.h> |
45 | #include <__type_traits/remove_cv.h> |
46 | #include <__type_traits/remove_cvref.h> |
47 | #include <__utility/forward.h> |
48 | |
49 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
50 | # pragma GCC system_header |
51 | #endif |
52 | |
53 | _LIBCPP_BEGIN_NAMESPACE_STD |
54 | |
55 | #if _LIBCPP_STD_VER >= 20 |
56 | |
57 | // [iterator.concept.readable] |
58 | template <class _In> |
59 | concept __indirectly_readable_impl = |
60 | requires(const _In __i) { |
61 | typename iter_value_t<_In>; |
62 | typename iter_reference_t<_In>; |
63 | typename iter_rvalue_reference_t<_In>; |
64 | { *__i } -> same_as<iter_reference_t<_In>>; |
65 | { ranges::iter_move(__i) } -> same_as<iter_rvalue_reference_t<_In>>; |
66 | } && common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> && |
67 | common_reference_with<iter_reference_t<_In>&&, iter_rvalue_reference_t<_In>&&> && |
68 | common_reference_with<iter_rvalue_reference_t<_In>&&, const iter_value_t<_In>&>; |
69 | |
70 | template <class _In> |
71 | concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>; |
72 | |
73 | template <class _Tp> |
74 | using __projected_iterator_t _LIBCPP_NODEBUG = typename _Tp::__projected_iterator; |
75 | |
76 | template <class _Tp> |
77 | using __projected_projection_t _LIBCPP_NODEBUG = typename _Tp::__projected_projection; |
78 | |
79 | template <class _Tp> |
80 | concept __specialization_of_projected = requires { |
81 | typename __projected_iterator_t<_Tp>; |
82 | typename __projected_projection_t<_Tp>; |
83 | } && __is_primary_template<_Tp>::value; |
84 | |
85 | template <class _Tp> |
86 | struct __indirect_value_t_impl { |
87 | using type _LIBCPP_NODEBUG = iter_value_t<_Tp>&; |
88 | }; |
89 | template <__specialization_of_projected _Tp> |
90 | struct __indirect_value_t_impl<_Tp> { |
91 | using type _LIBCPP_NODEBUG = |
92 | invoke_result_t<__projected_projection_t<_Tp>&, |
93 | typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>; |
94 | }; |
95 | |
96 | template <indirectly_readable _Tp> |
97 | using __indirect_value_t _LIBCPP_NODEBUG = typename __indirect_value_t_impl<_Tp>::type; |
98 | |
99 | template <indirectly_readable _Tp> |
100 | using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, __indirect_value_t<_Tp>>; |
101 | |
102 | // [iterator.concept.writable] |
103 | template <class _Out, class _Tp> |
104 | concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) { |
105 | *__o = std::forward<_Tp>(__t); // not required to be equality-preserving |
106 | *std::forward<_Out>(__o) = std::forward<_Tp>(__t); // not required to be equality-preserving |
107 | const_cast<const iter_reference_t<_Out>&&>(*__o) = std::forward<_Tp>(__t); // not required to be equality-preserving |
108 | const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o)) = |
109 | std::forward<_Tp>(__t); // not required to be equality-preserving |
110 | }; |
111 | |
112 | // [iterator.concept.winc] |
113 | template <class _Tp> |
114 | concept __integer_like = integral<_Tp> && !same_as<_Tp, bool>; |
115 | |
116 | template <class _Tp> |
117 | concept __signed_integer_like = signed_integral<_Tp>; |
118 | |
119 | template <class _Ip> |
120 | concept weakly_incrementable = |
121 | // TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173). |
122 | !same_as<_Ip, bool> && // Currently, clang does not handle bool correctly. |
123 | movable<_Ip> && requires(_Ip __i) { |
124 | typename iter_difference_t<_Ip>; |
125 | requires __signed_integer_like<iter_difference_t<_Ip>>; |
126 | { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving |
127 | __i++; // not required to be equality-preserving |
128 | }; |
129 | |
130 | // [iterator.concept.inc] |
131 | template <class _Ip> |
132 | concept incrementable = regular<_Ip> && weakly_incrementable<_Ip> && requires(_Ip __i) { |
133 | { __i++ } -> same_as<_Ip>; |
134 | }; |
135 | |
136 | // [iterator.concept.iterator] |
137 | template <class _Ip> |
138 | concept input_or_output_iterator = requires(_Ip __i) { |
139 | { *__i } -> __referenceable; |
140 | } && weakly_incrementable<_Ip>; |
141 | |
142 | // [iterator.concept.sentinel] |
143 | template <class _Sp, class _Ip> |
144 | concept sentinel_for = semiregular<_Sp> && input_or_output_iterator<_Ip> && __weakly_equality_comparable_with<_Sp, _Ip>; |
145 | |
146 | template <class, class> |
147 | inline constexpr bool disable_sized_sentinel_for = false; |
148 | |
149 | template <class _Sp, class _Ip> |
150 | concept sized_sentinel_for = |
151 | sentinel_for<_Sp, _Ip> && !disable_sized_sentinel_for<remove_cv_t<_Sp>, remove_cv_t<_Ip>> && |
152 | requires(const _Ip& __i, const _Sp& __s) { |
153 | { __s - __i } -> same_as<iter_difference_t<_Ip>>; |
154 | { __i - __s } -> same_as<iter_difference_t<_Ip>>; |
155 | }; |
156 | |
157 | template <class _Iter> |
158 | struct __iter_traits_cache { |
159 | using type _LIBCPP_NODEBUG = |
160 | _If<__is_primary_template<iterator_traits<_Iter> >::value, _Iter, iterator_traits<_Iter> >; |
161 | }; |
162 | template <class _Iter> |
163 | using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type; |
164 | |
165 | struct __iter_concept_concept_test { |
166 | template <class _Iter> |
167 | using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept; |
168 | }; |
169 | struct __iter_concept_category_test { |
170 | template <class _Iter> |
171 | using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category; |
172 | }; |
173 | struct __iter_concept_random_fallback { |
174 | template <class _Iter> |
175 | using _Apply _LIBCPP_NODEBUG = |
176 | __enable_if_t<__is_primary_template<iterator_traits<_Iter> >::value, random_access_iterator_tag>; |
177 | }; |
178 | |
179 | template <class _Iter, class _Tester> |
180 | struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {}; |
181 | |
182 | template <class _Iter> |
183 | struct __iter_concept_cache { |
184 | using type _LIBCPP_NODEBUG = |
185 | _Or<__test_iter_concept<_Iter, __iter_concept_concept_test>, |
186 | __test_iter_concept<_Iter, __iter_concept_category_test>, |
187 | __test_iter_concept<_Iter, __iter_concept_random_fallback> >; |
188 | }; |
189 | |
190 | template <class _Iter> |
191 | using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; |
192 | |
193 | // [iterator.concept.input] |
194 | template <class _Ip> |
195 | concept input_iterator = input_or_output_iterator<_Ip> && indirectly_readable<_Ip> && requires { |
196 | typename _ITER_CONCEPT<_Ip>; |
197 | } && derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; |
198 | |
199 | // [iterator.concept.output] |
200 | template <class _Ip, class _Tp> |
201 | concept output_iterator = |
202 | input_or_output_iterator<_Ip> && indirectly_writable<_Ip, _Tp> && requires(_Ip __it, _Tp&& __t) { |
203 | *__it++ = std::forward<_Tp>(__t); // not required to be equality-preserving |
204 | }; |
205 | |
206 | // [iterator.concept.forward] |
207 | template <class _Ip> |
208 | concept forward_iterator = |
209 | input_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, forward_iterator_tag> && incrementable<_Ip> && |
210 | sentinel_for<_Ip, _Ip>; |
211 | |
212 | // [iterator.concept.bidir] |
213 | template <class _Ip> |
214 | concept bidirectional_iterator = |
215 | forward_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, bidirectional_iterator_tag> && requires(_Ip __i) { |
216 | { --__i } -> same_as<_Ip&>; |
217 | { __i-- } -> same_as<_Ip>; |
218 | }; |
219 | |
220 | template <class _Ip> |
221 | concept random_access_iterator = |
222 | bidirectional_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> && |
223 | totally_ordered<_Ip> && sized_sentinel_for<_Ip, _Ip> && |
224 | requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) { |
225 | { __i += __n } -> same_as<_Ip&>; |
226 | { __j + __n } -> same_as<_Ip>; |
227 | { __n + __j } -> same_as<_Ip>; |
228 | { __i -= __n } -> same_as<_Ip&>; |
229 | { __j - __n } -> same_as<_Ip>; |
230 | { __j[__n] } -> same_as<iter_reference_t<_Ip>>; |
231 | }; |
232 | |
233 | template <class _Ip> |
234 | concept contiguous_iterator = |
235 | random_access_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && |
236 | is_lvalue_reference_v<iter_reference_t<_Ip>> && same_as<iter_value_t<_Ip>, remove_cvref_t<iter_reference_t<_Ip>>> && |
237 | requires(const _Ip& __i) { |
238 | { std::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>; |
239 | }; |
240 | |
241 | template <class _Ip> |
242 | concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); }); |
243 | |
244 | // [indirectcallable.indirectinvocable] |
245 | template <class _Fp, class _It> |
246 | concept indirectly_unary_invocable = |
247 | indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, __indirect_value_t<_It>> && |
248 | invocable<_Fp&, iter_reference_t<_It>> && |
249 | common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>, |
250 | invoke_result_t<_Fp&, iter_reference_t<_It>>>; |
251 | |
252 | template <class _Fp, class _It> |
253 | concept indirectly_regular_unary_invocable = |
254 | indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, __indirect_value_t<_It>> && |
255 | regular_invocable<_Fp&, iter_reference_t<_It>> && |
256 | common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>, |
257 | invoke_result_t<_Fp&, iter_reference_t<_It>>>; |
258 | |
259 | template <class _Fp, class _It> |
260 | concept indirect_unary_predicate = |
261 | indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, __indirect_value_t<_It>> && |
262 | predicate<_Fp&, iter_reference_t<_It>>; |
263 | |
264 | template <class _Fp, class _It1, class _It2> |
265 | concept indirect_binary_predicate = |
266 | indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> && |
267 | predicate<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> && |
268 | predicate<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> && |
269 | predicate<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> && |
270 | predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>; |
271 | |
272 | template <class _Fp, class _It1, class _It2 = _It1> |
273 | concept indirect_equivalence_relation = |
274 | indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> && |
275 | equivalence_relation<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> && |
276 | equivalence_relation<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> && |
277 | equivalence_relation<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> && |
278 | equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>; |
279 | |
280 | template <class _Fp, class _It1, class _It2 = _It1> |
281 | concept indirect_strict_weak_order = |
282 | indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> && |
283 | strict_weak_order<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> && |
284 | strict_weak_order<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> && |
285 | strict_weak_order<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> && |
286 | strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>; |
287 | |
288 | template <class _Fp, class... _Its> |
289 | requires(indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...> |
290 | using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>; |
291 | |
292 | template <class _In, class _Out> |
293 | concept indirectly_movable = indirectly_readable<_In> && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; |
294 | |
295 | template <class _In, class _Out> |
296 | concept indirectly_movable_storable = |
297 | indirectly_movable<_In, _Out> && indirectly_writable<_Out, iter_value_t<_In>> && movable<iter_value_t<_In>> && |
298 | constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> && |
299 | assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>; |
300 | |
301 | template <class _In, class _Out> |
302 | concept indirectly_copyable = indirectly_readable<_In> && indirectly_writable<_Out, iter_reference_t<_In>>; |
303 | |
304 | template <class _In, class _Out> |
305 | concept indirectly_copyable_storable = |
306 | indirectly_copyable<_In, _Out> && indirectly_writable<_Out, iter_value_t<_In>&> && |
307 | indirectly_writable<_Out, const iter_value_t<_In>&> && indirectly_writable<_Out, iter_value_t<_In>&&> && |
308 | indirectly_writable<_Out, const iter_value_t<_In>&&> && copyable<iter_value_t<_In>> && |
309 | constructible_from<iter_value_t<_In>, iter_reference_t<_In>> && |
310 | assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>; |
311 | |
312 | // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle |
313 | // (both iter_swap and indirectly_swappable require indirectly_readable). |
314 | |
315 | #endif // _LIBCPP_STD_VER >= 20 |
316 | |
317 | template <class _Tp> |
318 | using __has_random_access_iterator_category_or_concept _LIBCPP_NODEBUG |
319 | #if _LIBCPP_STD_VER >= 20 |
320 | = integral_constant<bool, random_access_iterator<_Tp>>; |
321 | #else // _LIBCPP_STD_VER < 20 |
322 | = __has_random_access_iterator_category<_Tp>; |
323 | #endif // _LIBCPP_STD_VER |
324 | |
325 | _LIBCPP_END_NAMESPACE_STD |
326 | |
327 | #endif // _LIBCPP___ITERATOR_CONCEPTS_H |
328 | |