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_constructible.h>
18 #include <__type_traits/is_convertible.h>
19 #include <__type_traits/is_signed.h>
20 #include <__type_traits/is_void.h>
21 #include <__utility/as_const.h>
22 #include <__utility/forward.h>
23 #include <__utility/move.h>
24 #include <__utility/swap.h>
26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27 # pragma GCC system_header
31 #include <__undef_macros>
33 #if _LIBCPP_STD_VER >= 20
35 _LIBCPP_BEGIN_NAMESPACE_STD
38 concept __cpp17_move_constructible
= is_move_constructible_v
<_Tp
>;
41 concept __cpp17_copy_constructible
= __cpp17_move_constructible
<_Tp
> && is_copy_constructible_v
<_Tp
>;
44 concept __cpp17_move_assignable
= requires(_Tp __lhs
, _Tp __rhs
) {
45 { __lhs
= std::move(__rhs
) } -> same_as
<_Tp
&>;
49 concept __cpp17_copy_assignable
= __cpp17_move_assignable
<_Tp
> && requires(_Tp __lhs
, _Tp __rhs
) {
50 { __lhs
= __rhs
} -> same_as
<_Tp
&>;
51 { __lhs
= std::as_const(__rhs
) } -> same_as
<_Tp
&>;
55 concept __cpp17_destructible
= requires(_Tp __v
) { __v
.~_Tp(); };
58 concept __cpp17_equality_comparable
= requires(_Tp __lhs
, _Tp __rhs
) {
59 { __lhs
== __rhs
} -> __boolean_testable
;
60 { std::as_const(__lhs
) == __rhs
} -> __boolean_testable
;
61 { __lhs
== std::as_const(__rhs
) } -> __boolean_testable
;
62 { std::as_const(__lhs
) == std::as_const(__rhs
) } -> __boolean_testable
;
66 concept __cpp17_default_constructible
= is_default_constructible_v
<_Tp
>;
68 template <class _Iter
>
69 concept __cpp17_iterator
=
70 __cpp17_copy_constructible
<_Iter
> && __cpp17_copy_assignable
<_Iter
> && __cpp17_destructible
<_Iter
> &&
71 (is_signed_v
<__iter_diff_t
<_Iter
>> || is_void_v
<__iter_diff_t
<_Iter
>>) && requires(_Iter __iter
) {
73 { ++__iter
} -> same_as
<_Iter
&>;
76 template <class _Iter
>
77 concept __cpp17_input_iterator
=
78 __cpp17_iterator
<_Iter
> && __cpp17_equality_comparable
<_Iter
> && requires(_Iter __lhs
, _Iter __rhs
) {
79 { __lhs
!= __rhs
} -> __boolean_testable
;
80 { std::as_const(__lhs
) != __rhs
} -> __boolean_testable
;
81 { __lhs
!= std::as_const(__rhs
) } -> __boolean_testable
;
82 { std::as_const(__lhs
) != std::as_const(__rhs
) } -> __boolean_testable
;
84 { *__lhs
} -> same_as
<__iter_reference
<_Iter
>>;
85 { *std::as_const(__lhs
) } -> same_as
<__iter_reference
<_Iter
>>;
87 { ++__lhs
} -> same_as
<_Iter
&>;
92 template <class _Iter
, class _WriteTo
>
93 concept __cpp17_output_iterator
= __cpp17_iterator
<_Iter
> && requires(_Iter __iter
, _WriteTo __write
) {
94 { *__iter
= std::forward
<_WriteTo
>(__write
) };
95 { ++__iter
} -> same_as
<_Iter
&>;
96 { __iter
++ } -> convertible_to
<const _Iter
&>;
97 { *__iter
++ = std::forward
<_WriteTo
>(__write
) };
100 template <class _Iter
>
101 concept __cpp17_forward_iterator
=
102 __cpp17_input_iterator
<_Iter
> && __cpp17_default_constructible
<_Iter
> && requires(_Iter __iter
) {
103 { __iter
++ } -> convertible_to
<const _Iter
&>;
104 { *__iter
++ } -> same_as
<__iter_reference
<_Iter
>>;
107 template <class _Iter
>
108 concept __cpp17_bidirectional_iterator
= __cpp17_forward_iterator
<_Iter
> && requires(_Iter __iter
) {
109 { --__iter
} -> same_as
<_Iter
&>;
110 { __iter
-- } -> convertible_to
<const _Iter
&>;
111 { *__iter
-- } -> same_as
<__iter_reference
<_Iter
>>;
114 template <class _Iter
>
115 concept __cpp17_random_access_iterator
=
116 __cpp17_bidirectional_iterator
<_Iter
> && requires(_Iter __iter
, __iter_diff_t
<_Iter
> __n
) {
117 { __iter
+= __n
} -> same_as
<_Iter
&>;
119 { __iter
+ __n
} -> same_as
<_Iter
>;
120 { __n
+ __iter
} -> same_as
<_Iter
>;
121 { std::as_const(__iter
) + __n
} -> same_as
<_Iter
>;
122 { __n
+ std::as_const(__iter
) } -> same_as
<_Iter
>;
124 { __iter
-= __n
} -> same_as
<_Iter
&>;
125 { __iter
- __n
} -> same_as
<_Iter
>;
126 { std::as_const(__iter
) - __n
} -> same_as
<_Iter
>;
128 { __iter
- __iter
} -> same_as
<__iter_diff_t
<_Iter
>>;
129 { std::as_const(__iter
) - __iter
} -> same_as
<__iter_diff_t
<_Iter
>>;
130 { __iter
- std::as_const(__iter
) } -> same_as
<__iter_diff_t
<_Iter
>>;
131 { std::as_const(__iter
) - std::as_const(__iter
) } -> same_as
<__iter_diff_t
<_Iter
>>;
133 { __iter
[__n
] } -> convertible_to
<__iter_reference
<_Iter
>>;
134 { std::as_const(__iter
)[__n
] } -> convertible_to
<__iter_reference
<_Iter
>>;
136 { __iter
< __iter
} -> __boolean_testable
;
137 { std::as_const(__iter
) < __iter
} -> __boolean_testable
;
138 { __iter
< std::as_const(__iter
) } -> __boolean_testable
;
139 { std::as_const(__iter
) < std::as_const(__iter
) } -> __boolean_testable
;
141 { __iter
> __iter
} -> __boolean_testable
;
142 { std::as_const(__iter
) > __iter
} -> __boolean_testable
;
143 { __iter
> std::as_const(__iter
) } -> __boolean_testable
;
144 { std::as_const(__iter
) > std::as_const(__iter
) } -> __boolean_testable
;
146 { __iter
>= __iter
} -> __boolean_testable
;
147 { std::as_const(__iter
) >= __iter
} -> __boolean_testable
;
148 { __iter
>= std::as_const(__iter
) } -> __boolean_testable
;
149 { std::as_const(__iter
) >= std::as_const(__iter
) } -> __boolean_testable
;
151 { __iter
<= __iter
} -> __boolean_testable
;
152 { std::as_const(__iter
) <= __iter
} -> __boolean_testable
;
153 { __iter
<= std::as_const(__iter
) } -> __boolean_testable
;
154 { std::as_const(__iter
) <= std::as_const(__iter
) } -> __boolean_testable
;
157 _LIBCPP_END_NAMESPACE_STD
159 # ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS
160 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) \
161 static_assert(::std::__cpp17_input_iterator<iter_t>, message)
162 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) \
163 static_assert(::std::__cpp17_output_iterator<iter_t, write_t>, message)
164 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) \
165 static_assert(::std::__cpp17_forward_iterator<iter_t>, message)
166 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) \
167 static_assert(::std::__cpp17_bidirectional_iterator<iter_t>, message)
168 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) \
169 static_assert(::std::__cpp17_random_access_iterator<iter_t>, message)
171 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) static_assert(true)
172 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) static_assert(true)
173 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) static_assert(true)
174 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) static_assert(true)
175 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) static_assert(true)
178 #else // _LIBCPP_STD_VER >= 20
180 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) static_assert(true)
181 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) static_assert(true)
182 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) static_assert(true)
183 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) static_assert(true)
184 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) static_assert(true)
186 #endif // _LIBCPP_STD_VER >= 20
190 #endif // _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H