1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H
10 #define _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H
12 #include <__concepts/boolean_testable.h>
13 #include <__concepts/convertible_to.h>
14 #include <__concepts/same_as.h>
16 #include <__iterator/iterator_traits.h>
17 #include <__type_traits/is_convertible.h>
18 #include <__type_traits/is_copy_constructible.h>
19 #include <__type_traits/is_default_constructible.h>
20 #include <__type_traits/is_move_constructible.h>
21 #include <__type_traits/is_signed.h>
22 #include <__type_traits/is_void.h>
23 #include <__utility/as_const.h>
24 #include <__utility/forward.h>
25 #include <__utility/move.h>
26 #include <__utility/swap.h>
28 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29 # pragma GCC system_header
32 #if _LIBCPP_STD_VER >= 20
34 _LIBCPP_BEGIN_NAMESPACE_STD
37 concept __cpp17_move_constructible
= is_move_constructible_v
<_Tp
>;
40 concept __cpp17_copy_constructible
= __cpp17_move_constructible
<_Tp
> && is_copy_constructible_v
<_Tp
>;
43 concept __cpp17_move_assignable
= requires(_Tp __lhs
, _Tp __rhs
) {
44 { __lhs
= std::move(__rhs
) } -> same_as
<_Tp
&>;
48 concept __cpp17_copy_assignable
= __cpp17_move_assignable
<_Tp
> && requires(_Tp __lhs
, _Tp __rhs
) {
49 { __lhs
= __rhs
} -> same_as
<_Tp
&>;
50 { __lhs
= std::as_const(__rhs
) } -> same_as
<_Tp
&>;
54 concept __cpp17_destructible
= requires(_Tp __v
) { __v
.~_Tp(); };
57 concept __cpp17_equality_comparable
= requires(_Tp __lhs
, _Tp __rhs
) {
58 { __lhs
== __rhs
} -> __boolean_testable
;
59 { std::as_const(__lhs
) == __rhs
} -> __boolean_testable
;
60 { __lhs
== std::as_const(__rhs
) } -> __boolean_testable
;
61 { std::as_const(__lhs
) == std::as_const(__rhs
) } -> __boolean_testable
;
65 concept __cpp17_default_constructible
= is_default_constructible_v
<_Tp
>;
67 template <class _Iter
>
68 concept __cpp17_iterator
=
69 __cpp17_copy_constructible
<_Iter
> && __cpp17_copy_assignable
<_Iter
> && __cpp17_destructible
<_Iter
> &&
70 (is_signed_v
<__iter_diff_t
<_Iter
>> || is_void_v
<__iter_diff_t
<_Iter
>>)&&requires(_Iter __iter
) {
72 { ++__iter
} -> same_as
<_Iter
&>;
75 template <class _Iter
>
76 concept __cpp17_input_iterator
=
77 __cpp17_iterator
<_Iter
> && __cpp17_equality_comparable
<_Iter
> && requires(_Iter __lhs
, _Iter __rhs
) {
78 { __lhs
!= __rhs
} -> __boolean_testable
;
79 { std::as_const(__lhs
) != __rhs
} -> __boolean_testable
;
80 { __lhs
!= std::as_const(__rhs
) } -> __boolean_testable
;
81 { std::as_const(__lhs
) != std::as_const(__rhs
) } -> __boolean_testable
;
83 { *__lhs
} -> same_as
<__iter_reference
<_Iter
>>;
84 { *std::as_const(__lhs
) } -> same_as
<__iter_reference
<_Iter
>>;
86 { ++__lhs
} -> same_as
<_Iter
&>;
91 template <class _Iter
, class _WriteTo
>
92 concept __cpp17_output_iterator
= __cpp17_iterator
<_Iter
> && requires(_Iter __iter
, _WriteTo __write
) {
93 { *__iter
= std::forward
<_WriteTo
>(__write
) };
94 { ++__iter
} -> same_as
<_Iter
&>;
95 { __iter
++ } -> convertible_to
<const _Iter
&>;
96 { *__iter
++ = std::forward
<_WriteTo
>(__write
) };
99 template <class _Iter
>
100 concept __cpp17_forward_iterator
=
101 __cpp17_input_iterator
<_Iter
> && __cpp17_default_constructible
<_Iter
> && requires(_Iter __iter
) {
102 { __iter
++ } -> convertible_to
<const _Iter
&>;
103 { *__iter
++ } -> same_as
<__iter_reference
<_Iter
>>;
106 template <class _Iter
>
107 concept __cpp17_bidirectional_iterator
= __cpp17_forward_iterator
<_Iter
> && requires(_Iter __iter
) {
108 { --__iter
} -> same_as
<_Iter
&>;
109 { __iter
-- } -> convertible_to
<const _Iter
&>;
110 { *__iter
-- } -> same_as
<__iter_reference
<_Iter
>>;
113 template <class _Iter
>
114 concept __cpp17_random_access_iterator
=
115 __cpp17_bidirectional_iterator
<_Iter
> && requires(_Iter __iter
, __iter_diff_t
<_Iter
> __n
) {
116 { __iter
+= __n
} -> same_as
<_Iter
&>;
118 { __iter
+ __n
} -> same_as
<_Iter
>;
119 { __n
+ __iter
} -> same_as
<_Iter
>;
120 { std::as_const(__iter
) + __n
} -> same_as
<_Iter
>;
121 { __n
+ std::as_const(__iter
) } -> same_as
<_Iter
>;
123 { __iter
-= __n
} -> same_as
<_Iter
&>;
124 { __iter
- __n
} -> same_as
<_Iter
>;
125 { std::as_const(__iter
) - __n
} -> same_as
<_Iter
>;
127 { __iter
- __iter
} -> same_as
<__iter_diff_t
<_Iter
>>;
128 { std::as_const(__iter
) - __iter
} -> same_as
<__iter_diff_t
<_Iter
>>;
129 { __iter
- std::as_const(__iter
) } -> same_as
<__iter_diff_t
<_Iter
>>;
130 { std::as_const(__iter
) - std::as_const(__iter
) } -> same_as
<__iter_diff_t
<_Iter
>>;
132 { __iter
[__n
] } -> convertible_to
<__iter_reference
<_Iter
>>;
133 { std::as_const(__iter
)[__n
] } -> convertible_to
<__iter_reference
<_Iter
>>;
135 { __iter
< __iter
} -> __boolean_testable
;
136 { std::as_const(__iter
) < __iter
} -> __boolean_testable
;
137 { __iter
< std::as_const(__iter
) } -> __boolean_testable
;
138 { std::as_const(__iter
) < std::as_const(__iter
) } -> __boolean_testable
;
140 { __iter
> __iter
} -> __boolean_testable
;
141 { std::as_const(__iter
) > __iter
} -> __boolean_testable
;
142 { __iter
> std::as_const(__iter
) } -> __boolean_testable
;
143 { std::as_const(__iter
) > std::as_const(__iter
) } -> __boolean_testable
;
145 { __iter
>= __iter
} -> __boolean_testable
;
146 { std::as_const(__iter
) >= __iter
} -> __boolean_testable
;
147 { __iter
>= std::as_const(__iter
) } -> __boolean_testable
;
148 { std::as_const(__iter
) >= std::as_const(__iter
) } -> __boolean_testable
;
150 { __iter
<= __iter
} -> __boolean_testable
;
151 { std::as_const(__iter
) <= __iter
} -> __boolean_testable
;
152 { __iter
<= std::as_const(__iter
) } -> __boolean_testable
;
153 { std::as_const(__iter
) <= std::as_const(__iter
) } -> __boolean_testable
;
156 _LIBCPP_END_NAMESPACE_STD
158 # ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS
159 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) static_assert(::std::__cpp17_input_iterator<iter_t>);
160 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) \
161 static_assert(::std::__cpp17_output_iterator<iter_t, write_t>);
162 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) static_assert(::std::__cpp17_forward_iterator<iter_t>);
163 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) \
164 static_assert(::std::__cpp17_bidirectional_iterator<iter_t>);
165 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) \
166 static_assert(::std::__cpp17_random_access_iterator<iter_t>);
168 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t)
169 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t)
170 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t)
171 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t)
172 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t)
175 #else // _LIBCPP_STD_VER >= 20
177 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t)
178 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t)
179 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t)
180 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t)
181 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t)
183 #endif // _LIBCPP_STD_VER >= 20
185 #endif // _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H