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_MOVE_ITERATOR_H
11 #define _LIBCPP___ITERATOR_MOVE_ITERATOR_H
13 #include <__compare/compare_three_way_result.h>
14 #include <__compare/three_way_comparable.h>
15 #include <__concepts/assignable.h>
16 #include <__concepts/convertible_to.h>
17 #include <__concepts/derived_from.h>
18 #include <__concepts/same_as.h>
20 #include <__iterator/concepts.h>
21 #include <__iterator/incrementable_traits.h>
22 #include <__iterator/iter_move.h>
23 #include <__iterator/iter_swap.h>
24 #include <__iterator/iterator_traits.h>
25 #include <__iterator/move_sentinel.h>
26 #include <__iterator/readable_traits.h>
27 #include <__type_traits/conditional.h>
28 #include <__type_traits/enable_if.h>
29 #include <__type_traits/is_assignable.h>
30 #include <__type_traits/is_constructible.h>
31 #include <__type_traits/is_convertible.h>
32 #include <__type_traits/is_reference.h>
33 #include <__type_traits/is_same.h>
34 #include <__type_traits/remove_reference.h>
35 #include <__utility/declval.h>
36 #include <__utility/move.h>
38 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
39 # pragma GCC system_header
43 #include <__undef_macros>
45 _LIBCPP_BEGIN_NAMESPACE_STD
47 #if _LIBCPP_STD_VER >= 20
48 template <class _Iter
, class = void>
49 struct __move_iter_category_base
{};
51 template <class _Iter
>
52 requires requires
{ typename iterator_traits
<_Iter
>::iterator_category
; }
53 struct __move_iter_category_base
<_Iter
> {
54 using iterator_category
=
55 _If
< derived_from
<typename iterator_traits
<_Iter
>::iterator_category
, random_access_iterator_tag
>,
56 random_access_iterator_tag
,
57 typename iterator_traits
<_Iter
>::iterator_category
>;
60 template <class _Iter
, class _Sent
>
61 concept __move_iter_comparable
= requires
{
62 { std::declval
<const _Iter
&>() == std::declval
<_Sent
>() } -> convertible_to
<bool>;
64 #endif // _LIBCPP_STD_VER >= 20
66 template <class _Iter
>
67 class _LIBCPP_TEMPLATE_VIS move_iterator
68 #if _LIBCPP_STD_VER >= 20
69 : public __move_iter_category_base
<_Iter
>
72 #if _LIBCPP_STD_VER >= 20
75 _LIBCPP_HIDE_FROM_ABI
static constexpr auto __get_iter_concept() {
76 if constexpr (random_access_iterator
<_Iter
>) {
77 return random_access_iterator_tag
{};
78 } else if constexpr (bidirectional_iterator
<_Iter
>) {
79 return bidirectional_iterator_tag
{};
80 } else if constexpr (forward_iterator
<_Iter
>) {
81 return forward_iterator_tag
{};
83 return input_iterator_tag
{};
86 #endif // _LIBCPP_STD_VER >= 20
89 #if _LIBCPP_STD_VER >= 20
90 using iterator_type
= _Iter
;
91 using iterator_concept
= decltype(__get_iter_concept());
92 // iterator_category is inherited and not always present
93 using value_type
= iter_value_t
<_Iter
>;
94 using difference_type
= iter_difference_t
<_Iter
>;
95 using pointer
= _Iter
;
96 using reference
= iter_rvalue_reference_t
<_Iter
>;
98 typedef _Iter iterator_type
;
99 typedef _If
< __has_random_access_iterator_category
<_Iter
>::value
,
100 random_access_iterator_tag
,
101 typename iterator_traits
<_Iter
>::iterator_category
>
103 typedef typename iterator_traits
<iterator_type
>::value_type value_type
;
104 typedef typename iterator_traits
<iterator_type
>::difference_type difference_type
;
105 typedef iterator_type pointer
;
107 typedef typename iterator_traits
<iterator_type
>::reference __reference
;
108 typedef __conditional_t
<is_reference
<__reference
>::value
, __libcpp_remove_reference_t
<__reference
>&&, __reference
>
110 #endif // _LIBCPP_STD_VER >= 20
112 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
explicit move_iterator(_Iter __i
) : __current_(std::move(__i
)) {}
114 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
& operator++() {
119 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer
operator->() const {
123 #if _LIBCPP_STD_VER >= 20
124 _LIBCPP_HIDE_FROM_ABI
constexpr move_iterator()
125 requires is_constructible_v
<_Iter
>
129 requires(!_IsSame
<_Up
, _Iter
>::value
) && convertible_to
<const _Up
&, _Iter
>
130 _LIBCPP_HIDE_FROM_ABI
constexpr move_iterator(const move_iterator
<_Up
>& __u
) : __current_(__u
.base()) {}
133 requires(!_IsSame
<_Up
, _Iter
>::value
) && convertible_to
<const _Up
&, _Iter
> && assignable_from
<_Iter
&, const _Up
&>
134 _LIBCPP_HIDE_FROM_ABI
constexpr move_iterator
& operator=(const move_iterator
<_Up
>& __u
) {
135 __current_
= __u
.base();
139 _LIBCPP_HIDE_FROM_ABI
constexpr const _Iter
& base() const& noexcept
{ return __current_
; }
140 _LIBCPP_HIDE_FROM_ABI
constexpr _Iter
base() && { return std::move(__current_
); }
142 _LIBCPP_HIDE_FROM_ABI
constexpr reference
operator*() const { return ranges::iter_move(__current_
); }
143 _LIBCPP_HIDE_FROM_ABI
constexpr reference
operator[](difference_type __n
) const {
144 return ranges::iter_move(__current_
+ __n
);
147 _LIBCPP_HIDE_FROM_ABI
constexpr auto operator++(int)
148 requires forward_iterator
<_Iter
>
150 move_iterator
__tmp(*this);
155 _LIBCPP_HIDE_FROM_ABI
constexpr void operator++(int) { ++__current_
; }
157 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
move_iterator() : __current_() {}
159 template <class _Up
, __enable_if_t
< !is_same
<_Up
, _Iter
>::value
&& is_convertible
<const _Up
&, _Iter
>::value
, int> = 0>
160 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
move_iterator(const move_iterator
<_Up
>& __u
)
161 : __current_(__u
.base()) {}
164 __enable_if_t
< !is_same
<_Up
, _Iter
>::value
&& is_convertible
<const _Up
&, _Iter
>::value
&&
165 is_assignable
<_Iter
&, const _Up
&>::value
,
167 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
& operator=(const move_iterator
<_Up
>& __u
) {
168 __current_
= __u
.base();
172 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Iter
base() const { return __current_
; }
174 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference
operator*() const {
175 return static_cast<reference
>(*__current_
);
177 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference
operator[](difference_type __n
) const {
178 return static_cast<reference
>(__current_
[__n
]);
181 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
operator++(int) {
182 move_iterator
__tmp(*this);
186 #endif // _LIBCPP_STD_VER >= 20
188 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
& operator--() {
192 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
operator--(int) {
193 move_iterator
__tmp(*this);
197 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
operator+(difference_type __n
) const {
198 return move_iterator(__current_
+ __n
);
200 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
& operator+=(difference_type __n
) {
204 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
operator-(difference_type __n
) const {
205 return move_iterator(__current_
- __n
);
207 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
& operator-=(difference_type __n
) {
212 #if _LIBCPP_STD_VER >= 20
213 template <sentinel_for
<_Iter
> _Sent
>
214 friend _LIBCPP_HIDE_FROM_ABI
constexpr bool operator==(const move_iterator
& __x
, const move_sentinel
<_Sent
>& __y
)
215 requires __move_iter_comparable
<_Iter
, _Sent
>
217 return __x
.base() == __y
.base();
220 template <sized_sentinel_for
<_Iter
> _Sent
>
221 friend _LIBCPP_HIDE_FROM_ABI
constexpr iter_difference_t
<_Iter
>
222 operator-(const move_sentinel
<_Sent
>& __x
, const move_iterator
& __y
) {
223 return __x
.base() - __y
.base();
226 template <sized_sentinel_for
<_Iter
> _Sent
>
227 friend _LIBCPP_HIDE_FROM_ABI
constexpr iter_difference_t
<_Iter
>
228 operator-(const move_iterator
& __x
, const move_sentinel
<_Sent
>& __y
) {
229 return __x
.base() - __y
.base();
232 friend _LIBCPP_HIDE_FROM_ABI
constexpr iter_rvalue_reference_t
<_Iter
>
233 iter_move(const move_iterator
& __i
) noexcept(noexcept(ranges::iter_move(__i
.__current_
))) {
234 return ranges::iter_move(__i
.__current_
);
237 template <indirectly_swappable
<_Iter
> _It2
>
238 friend _LIBCPP_HIDE_FROM_ABI
constexpr void
239 iter_swap(const move_iterator
& __x
,
240 const move_iterator
<_It2
>& __y
) noexcept(noexcept(ranges::iter_swap(__x
.__current_
, __y
.__current_
))) {
241 return ranges::iter_swap(__x
.__current_
, __y
.__current_
);
243 #endif // _LIBCPP_STD_VER >= 20
246 template <class _It2
>
247 friend class move_iterator
;
251 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator
);
253 template <class _Iter1
, class _Iter2
>
254 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
bool
255 operator==(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
256 return __x
.base() == __y
.base();
259 #if _LIBCPP_STD_VER <= 17
260 template <class _Iter1
, class _Iter2
>
261 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
bool
262 operator!=(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
263 return __x
.base() != __y
.base();
265 #endif // _LIBCPP_STD_VER <= 17
267 template <class _Iter1
, class _Iter2
>
268 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
bool
269 operator<(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
270 return __x
.base() < __y
.base();
273 template <class _Iter1
, class _Iter2
>
274 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
bool
275 operator>(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
276 return __x
.base() > __y
.base();
279 template <class _Iter1
, class _Iter2
>
280 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
bool
281 operator<=(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
282 return __x
.base() <= __y
.base();
285 template <class _Iter1
, class _Iter2
>
286 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
bool
287 operator>=(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
288 return __x
.base() >= __y
.base();
291 #if _LIBCPP_STD_VER >= 20
292 template <class _Iter1
, three_way_comparable_with
<_Iter1
> _Iter2
>
293 inline _LIBCPP_HIDE_FROM_ABI
constexpr auto
294 operator<=>(const move_iterator
<_Iter1
>& __x
,
295 const move_iterator
<_Iter2
>& __y
) -> compare_three_way_result_t
<_Iter1
, _Iter2
> {
296 return __x
.base() <=> __y
.base();
298 #endif // _LIBCPP_STD_VER >= 20
300 #ifndef _LIBCPP_CXX03_LANG
301 template <class _Iter1
, class _Iter2
>
302 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
auto
303 operator-(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) -> decltype(__x
.base() - __y
.base()) {
304 return __x
.base() - __y
.base();
307 template <class _Iter1
, class _Iter2
>
308 inline _LIBCPP_HIDE_FROM_ABI typename move_iterator
<_Iter1
>::difference_type
309 operator-(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
) {
310 return __x
.base() - __y
.base();
312 #endif // !_LIBCPP_CXX03_LANG
314 #if _LIBCPP_STD_VER >= 20
315 template <class _Iter
>
316 inline _LIBCPP_HIDE_FROM_ABI
constexpr move_iterator
<_Iter
>
317 operator+(iter_difference_t
<_Iter
> __n
, const move_iterator
<_Iter
>& __x
)
319 { __x
.base() + __n
} -> same_as
<_Iter
>;
325 template <class _Iter
>
326 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
<_Iter
>
327 operator+(typename move_iterator
<_Iter
>::difference_type __n
, const move_iterator
<_Iter
>& __x
) {
328 return move_iterator
<_Iter
>(__x
.base() + __n
);
330 #endif // _LIBCPP_STD_VER >= 20
332 #if _LIBCPP_STD_VER >= 20
333 template <class _Iter1
, class _Iter2
>
334 requires(!sized_sentinel_for
<_Iter1
, _Iter2
>)
335 inline constexpr bool disable_sized_sentinel_for
<move_iterator
<_Iter1
>, move_iterator
<_Iter2
>> = true;
336 #endif // _LIBCPP_STD_VER >= 20
338 template <class _Iter
>
339 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator
<_Iter
> make_move_iterator(_Iter __i
) {
340 return move_iterator
<_Iter
>(std::move(__i
));
343 _LIBCPP_END_NAMESPACE_STD
347 #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H