2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___ITERATOR_CONCEPTS_H
11 #define _LIBCPP___ITERATOR_CONCEPTS_H
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>
29 #include <__functional/invoke.h>
30 #include <__iterator/incrementable_traits.h>
31 #include <__iterator/iter_move.h>
32 #include <__iterator/iterator_traits.h>
33 #include <__iterator/readable_traits.h>
34 #include <__memory/pointer_traits.h>
35 #include <__type_traits/add_pointer.h>
36 #include <__type_traits/common_reference.h>
37 #include <__type_traits/is_pointer.h>
38 #include <__type_traits/is_reference.h>
39 #include <__type_traits/remove_cv.h>
40 #include <__type_traits/remove_cvref.h>
41 #include <__utility/forward.h>
43 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
44 # pragma GCC system_header
47 _LIBCPP_BEGIN_NAMESPACE_STD
49 #if _LIBCPP_STD_VER >= 20
51 // [iterator.concept.readable]
53 concept __indirectly_readable_impl
=
54 requires(const _In __i
) {
55 typename iter_value_t
<_In
>;
56 typename iter_reference_t
<_In
>;
57 typename iter_rvalue_reference_t
<_In
>;
58 { *__i
} -> same_as
<iter_reference_t
<_In
>>;
59 { ranges::iter_move(__i
) } -> same_as
<iter_rvalue_reference_t
<_In
>>;
60 } && common_reference_with
<iter_reference_t
<_In
>&&, iter_value_t
<_In
>&> &&
61 common_reference_with
<iter_reference_t
<_In
>&&, iter_rvalue_reference_t
<_In
>&&> &&
62 common_reference_with
<iter_rvalue_reference_t
<_In
>&&, const iter_value_t
<_In
>&>;
65 concept indirectly_readable
= __indirectly_readable_impl
<remove_cvref_t
<_In
>>;
67 template <indirectly_readable _Tp
>
68 using iter_common_reference_t
= common_reference_t
<iter_reference_t
<_Tp
>, iter_value_t
<_Tp
>&>;
70 // [iterator.concept.writable]
71 template <class _Out
, class _Tp
>
72 concept indirectly_writable
= requires(_Out
&& __o
, _Tp
&& __t
) {
73 *__o
= std::forward
<_Tp
>(__t
); // not required to be equality-preserving
74 *std::forward
<_Out
>(__o
) = std::forward
<_Tp
>(__t
); // not required to be equality-preserving
75 const_cast<const iter_reference_t
<_Out
>&&>(*__o
) = std::forward
<_Tp
>(__t
); // not required to be equality-preserving
76 const_cast<const iter_reference_t
<_Out
>&&>(*std::forward
<_Out
>(__o
)) =
77 std::forward
<_Tp
>(__t
); // not required to be equality-preserving
80 // [iterator.concept.winc]
82 concept __integer_like
= integral
<_Tp
> && !same_as
<_Tp
, bool>;
85 concept __signed_integer_like
= signed_integral
<_Tp
>;
88 concept weakly_incrementable
=
89 // TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173).
90 !same_as
<_Ip
, bool> && // Currently, clang does not handle bool correctly.
91 movable
<_Ip
> && requires(_Ip __i
) {
92 typename iter_difference_t
<_Ip
>;
93 requires __signed_integer_like
<iter_difference_t
<_Ip
>>;
94 { ++__i
} -> same_as
<_Ip
&>; // not required to be equality-preserving
95 __i
++; // not required to be equality-preserving
98 // [iterator.concept.inc]
100 concept incrementable
= regular
<_Ip
> && weakly_incrementable
<_Ip
> && requires(_Ip __i
) {
101 { __i
++ } -> same_as
<_Ip
>;
104 // [iterator.concept.iterator]
106 concept input_or_output_iterator
= requires(_Ip __i
) {
107 { *__i
} -> __can_reference
;
108 } && weakly_incrementable
<_Ip
>;
110 // [iterator.concept.sentinel]
111 template <class _Sp
, class _Ip
>
112 concept sentinel_for
= semiregular
<_Sp
> && input_or_output_iterator
<_Ip
> && __weakly_equality_comparable_with
<_Sp
, _Ip
>;
114 template <class, class>
115 inline constexpr bool disable_sized_sentinel_for
= false;
117 template <class _Sp
, class _Ip
>
118 concept sized_sentinel_for
=
119 sentinel_for
<_Sp
, _Ip
> && !disable_sized_sentinel_for
<remove_cv_t
<_Sp
>, remove_cv_t
<_Ip
>> &&
120 requires(const _Ip
& __i
, const _Sp
& __s
) {
121 { __s
- __i
} -> same_as
<iter_difference_t
<_Ip
>>;
122 { __i
- __s
} -> same_as
<iter_difference_t
<_Ip
>>;
125 // [iterator.concept.input]
127 concept input_iterator
= input_or_output_iterator
<_Ip
> && indirectly_readable
<_Ip
> && requires
{
128 typename _ITER_CONCEPT
<_Ip
>;
129 } && derived_from
<_ITER_CONCEPT
<_Ip
>, input_iterator_tag
>;
131 // [iterator.concept.output]
132 template <class _Ip
, class _Tp
>
133 concept output_iterator
=
134 input_or_output_iterator
<_Ip
> && indirectly_writable
<_Ip
, _Tp
> && requires(_Ip __it
, _Tp
&& __t
) {
135 *__it
++ = std::forward
<_Tp
>(__t
); // not required to be equality-preserving
138 // [iterator.concept.forward]
140 concept forward_iterator
=
141 input_iterator
<_Ip
> && derived_from
<_ITER_CONCEPT
<_Ip
>, forward_iterator_tag
> && incrementable
<_Ip
> &&
142 sentinel_for
<_Ip
, _Ip
>;
144 // [iterator.concept.bidir]
146 concept bidirectional_iterator
=
147 forward_iterator
<_Ip
> && derived_from
<_ITER_CONCEPT
<_Ip
>, bidirectional_iterator_tag
> && requires(_Ip __i
) {
148 { --__i
} -> same_as
<_Ip
&>;
149 { __i
-- } -> same_as
<_Ip
>;
153 concept random_access_iterator
=
154 bidirectional_iterator
<_Ip
> && derived_from
<_ITER_CONCEPT
<_Ip
>, random_access_iterator_tag
> &&
155 totally_ordered
<_Ip
> && sized_sentinel_for
<_Ip
, _Ip
> &&
156 requires(_Ip __i
, const _Ip __j
, const iter_difference_t
<_Ip
> __n
) {
157 { __i
+= __n
} -> same_as
<_Ip
&>;
158 { __j
+ __n
} -> same_as
<_Ip
>;
159 { __n
+ __j
} -> same_as
<_Ip
>;
160 { __i
-= __n
} -> same_as
<_Ip
&>;
161 { __j
- __n
} -> same_as
<_Ip
>;
162 { __j
[__n
] } -> same_as
<iter_reference_t
<_Ip
>>;
166 concept contiguous_iterator
=
167 random_access_iterator
<_Ip
> && derived_from
<_ITER_CONCEPT
<_Ip
>, contiguous_iterator_tag
> &&
168 is_lvalue_reference_v
<iter_reference_t
<_Ip
>> && same_as
<iter_value_t
<_Ip
>, remove_cvref_t
<iter_reference_t
<_Ip
>>> &&
169 requires(const _Ip
& __i
) {
170 { std::to_address(__i
) } -> same_as
<add_pointer_t
<iter_reference_t
<_Ip
>>>;
174 concept __has_arrow
= input_iterator
<_Ip
> && (is_pointer_v
<_Ip
> || requires(_Ip __i
) { __i
.operator->(); });
176 // [indirectcallable.indirectinvocable]
177 template <class _Fp
, class _It
>
178 concept indirectly_unary_invocable
=
179 indirectly_readable
<_It
> && copy_constructible
<_Fp
> && invocable
<_Fp
&, iter_value_t
<_It
>&> &&
180 invocable
<_Fp
&, iter_reference_t
<_It
>> &&
181 common_reference_with
< invoke_result_t
<_Fp
&, iter_value_t
<_It
>&>, invoke_result_t
<_Fp
&, iter_reference_t
<_It
>>>;
183 template <class _Fp
, class _It
>
184 concept indirectly_regular_unary_invocable
=
185 indirectly_readable
<_It
> && copy_constructible
<_Fp
> && regular_invocable
<_Fp
&, iter_value_t
<_It
>&> &&
186 regular_invocable
<_Fp
&, iter_reference_t
<_It
>> &&
187 common_reference_with
< invoke_result_t
<_Fp
&, iter_value_t
<_It
>&>, invoke_result_t
<_Fp
&, iter_reference_t
<_It
>>>;
189 template <class _Fp
, class _It
>
190 concept indirect_unary_predicate
=
191 indirectly_readable
<_It
> && copy_constructible
<_Fp
> && predicate
<_Fp
&, iter_value_t
<_It
>&> &&
192 predicate
<_Fp
&, iter_reference_t
<_It
>>;
194 template <class _Fp
, class _It1
, class _It2
>
195 concept indirect_binary_predicate
=
196 indirectly_readable
<_It1
> && indirectly_readable
<_It2
> && copy_constructible
<_Fp
> &&
197 predicate
<_Fp
&, iter_value_t
<_It1
>&, iter_value_t
<_It2
>&> &&
198 predicate
<_Fp
&, iter_value_t
<_It1
>&, iter_reference_t
<_It2
>> &&
199 predicate
<_Fp
&, iter_reference_t
<_It1
>, iter_value_t
<_It2
>&> &&
200 predicate
<_Fp
&, iter_reference_t
<_It1
>, iter_reference_t
<_It2
>>;
202 template <class _Fp
, class _It1
, class _It2
= _It1
>
203 concept indirect_equivalence_relation
=
204 indirectly_readable
<_It1
> && indirectly_readable
<_It2
> && copy_constructible
<_Fp
> &&
205 equivalence_relation
<_Fp
&, iter_value_t
<_It1
>&, iter_value_t
<_It2
>&> &&
206 equivalence_relation
<_Fp
&, iter_value_t
<_It1
>&, iter_reference_t
<_It2
>> &&
207 equivalence_relation
<_Fp
&, iter_reference_t
<_It1
>, iter_value_t
<_It2
>&> &&
208 equivalence_relation
<_Fp
&, iter_reference_t
<_It1
>, iter_reference_t
<_It2
>>;
210 template <class _Fp
, class _It1
, class _It2
= _It1
>
211 concept indirect_strict_weak_order
=
212 indirectly_readable
<_It1
> && indirectly_readable
<_It2
> && copy_constructible
<_Fp
> &&
213 strict_weak_order
<_Fp
&, iter_value_t
<_It1
>&, iter_value_t
<_It2
>&> &&
214 strict_weak_order
<_Fp
&, iter_value_t
<_It1
>&, iter_reference_t
<_It2
>> &&
215 strict_weak_order
<_Fp
&, iter_reference_t
<_It1
>, iter_value_t
<_It2
>&> &&
216 strict_weak_order
<_Fp
&, iter_reference_t
<_It1
>, iter_reference_t
<_It2
>>;
218 template <class _Fp
, class... _Its
>
219 requires(indirectly_readable
<_Its
> && ...) && invocable
<_Fp
, iter_reference_t
<_Its
>...>
220 using indirect_result_t
= invoke_result_t
<_Fp
, iter_reference_t
<_Its
>...>;
222 template <class _In
, class _Out
>
223 concept indirectly_movable
= indirectly_readable
<_In
> && indirectly_writable
<_Out
, iter_rvalue_reference_t
<_In
>>;
225 template <class _In
, class _Out
>
226 concept indirectly_movable_storable
=
227 indirectly_movable
<_In
, _Out
> && indirectly_writable
<_Out
, iter_value_t
<_In
>> && movable
<iter_value_t
<_In
>> &&
228 constructible_from
<iter_value_t
<_In
>, iter_rvalue_reference_t
<_In
>> &&
229 assignable_from
<iter_value_t
<_In
>&, iter_rvalue_reference_t
<_In
>>;
231 template <class _In
, class _Out
>
232 concept indirectly_copyable
= indirectly_readable
<_In
> && indirectly_writable
<_Out
, iter_reference_t
<_In
>>;
234 template <class _In
, class _Out
>
235 concept indirectly_copyable_storable
=
236 indirectly_copyable
<_In
, _Out
> && indirectly_writable
<_Out
, iter_value_t
<_In
>&> &&
237 indirectly_writable
<_Out
, const iter_value_t
<_In
>&> && indirectly_writable
<_Out
, iter_value_t
<_In
>&&> &&
238 indirectly_writable
<_Out
, const iter_value_t
<_In
>&&> && copyable
<iter_value_t
<_In
>> &&
239 constructible_from
<iter_value_t
<_In
>, iter_reference_t
<_In
>> &&
240 assignable_from
<iter_value_t
<_In
>&, iter_reference_t
<_In
>>;
242 // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle
243 // (both iter_swap and indirectly_swappable require indirectly_readable).
245 #endif // _LIBCPP_STD_VER >= 20
248 using __has_random_access_iterator_category_or_concept
249 #if _LIBCPP_STD_VER >= 20
250 = integral_constant
<bool, random_access_iterator
<_Tp
>>;
251 #else // _LIBCPP_STD_VER < 20
252 = __has_random_access_iterator_category
<_Tp
>;
253 #endif // _LIBCPP_STD_VER
255 _LIBCPP_END_NAMESPACE_STD
257 #endif // _LIBCPP___ITERATOR_CONCEPTS_H