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
{};
52 requires requires
{ typename iterator_traits
<_Iter
>::iterator_category
; }
53 struct __move_iter_category_base
<_Iter
> {
54 using iterator_category
= _If
<
55 derived_from
<typename iterator_traits
<_Iter
>::iterator_category
, random_access_iterator_tag
>,
56 random_access_iterator_tag
,
57 typename iterator_traits
<_Iter
>::iterator_category
61 template<class _Iter
, class _Sent
>
62 concept __move_iter_comparable
= requires
{
63 { std::declval
<const _Iter
&>() == std::declval
<_Sent
>() } -> convertible_to
<bool>;
65 #endif // _LIBCPP_STD_VER >= 20
67 template <class _Iter
>
68 class _LIBCPP_TEMPLATE_VIS move_iterator
69 #if _LIBCPP_STD_VER >= 20
70 : public __move_iter_category_base
<_Iter
>
73 #if _LIBCPP_STD_VER >= 20
76 static constexpr auto __get_iter_concept() {
77 if constexpr (random_access_iterator
<_Iter
>) {
78 return random_access_iterator_tag
{};
79 } else if constexpr (bidirectional_iterator
<_Iter
>) {
80 return bidirectional_iterator_tag
{};
81 } else if constexpr (forward_iterator
<_Iter
>) {
82 return forward_iterator_tag
{};
84 return input_iterator_tag
{};
87 #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
;
100 __has_random_access_iterator_category
<_Iter
>::value
,
101 random_access_iterator_tag
,
102 typename iterator_traits
<_Iter
>::iterator_category
104 typedef typename iterator_traits
<iterator_type
>::value_type value_type
;
105 typedef typename iterator_traits
<iterator_type
>::difference_type difference_type
;
106 typedef iterator_type pointer
;
108 typedef typename iterator_traits
<iterator_type
>::reference __reference
;
109 typedef typename conditional
<
110 is_reference
<__reference
>::value
,
111 __libcpp_remove_reference_t
<__reference
>&&,
114 #endif // _LIBCPP_STD_VER >= 20
116 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
117 explicit move_iterator(_Iter __i
) : __current_(std::move(__i
)) {}
119 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
120 move_iterator
& operator++() { ++__current_
; return *this; }
122 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
123 pointer
operator->() const { return __current_
; }
125 #if _LIBCPP_STD_VER >= 20
126 _LIBCPP_HIDE_FROM_ABI
constexpr
127 move_iterator() requires is_constructible_v
<_Iter
> : __current_() {}
130 requires (!_IsSame
<_Up
, _Iter
>::value
) && convertible_to
<const _Up
&, _Iter
>
131 _LIBCPP_HIDE_FROM_ABI
constexpr
132 move_iterator(const move_iterator
<_Up
>& __u
) : __current_(__u
.base()) {}
135 requires (!_IsSame
<_Up
, _Iter
>::value
) &&
136 convertible_to
<const _Up
&, _Iter
> &&
137 assignable_from
<_Iter
&, const _Up
&>
138 _LIBCPP_HIDE_FROM_ABI
constexpr
139 move_iterator
& operator=(const move_iterator
<_Up
>& __u
) {
140 __current_
= __u
.base();
144 _LIBCPP_HIDE_FROM_ABI
constexpr const _Iter
& base() const & noexcept
{ return __current_
; }
145 _LIBCPP_HIDE_FROM_ABI
constexpr _Iter
base() && { return std::move(__current_
); }
147 _LIBCPP_HIDE_FROM_ABI
constexpr
148 reference
operator*() const { return ranges::iter_move(__current_
); }
149 _LIBCPP_HIDE_FROM_ABI
constexpr
150 reference
operator[](difference_type __n
) const { return ranges::iter_move(__current_
+ __n
); }
152 _LIBCPP_HIDE_FROM_ABI
constexpr
154 requires forward_iterator
<_Iter
>
156 move_iterator
__tmp(*this); ++__current_
; return __tmp
;
159 _LIBCPP_HIDE_FROM_ABI
constexpr
160 void operator++(int) { ++__current_
; }
162 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
163 move_iterator() : __current_() {}
165 template <class _Up
, class = __enable_if_t
<
166 !is_same
<_Up
, _Iter
>::value
&& is_convertible
<const _Up
&, _Iter
>::value
168 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
169 move_iterator(const move_iterator
<_Up
>& __u
) : __current_(__u
.base()) {}
171 template <class _Up
, class = __enable_if_t
<
172 !is_same
<_Up
, _Iter
>::value
&&
173 is_convertible
<const _Up
&, _Iter
>::value
&&
174 is_assignable
<_Iter
&, const _Up
&>::value
176 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
177 move_iterator
& operator=(const move_iterator
<_Up
>& __u
) {
178 __current_
= __u
.base();
182 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
183 _Iter
base() const { return __current_
; }
185 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
186 reference
operator*() const { return static_cast<reference
>(*__current_
); }
187 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
188 reference
operator[](difference_type __n
) const { return static_cast<reference
>(__current_
[__n
]); }
190 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
191 move_iterator
operator++(int) { move_iterator
__tmp(*this); ++__current_
; return __tmp
; }
192 #endif // _LIBCPP_STD_VER >= 20
194 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
195 move_iterator
& operator--() { --__current_
; return *this; }
196 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
197 move_iterator
operator--(int) { move_iterator
__tmp(*this); --__current_
; return __tmp
; }
198 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
199 move_iterator
operator+(difference_type __n
) const { return move_iterator(__current_
+ __n
); }
200 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
201 move_iterator
& operator+=(difference_type __n
) { __current_
+= __n
; return *this; }
202 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
203 move_iterator
operator-(difference_type __n
) const { return move_iterator(__current_
- __n
); }
204 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
205 move_iterator
& operator-=(difference_type __n
) { __current_
-= __n
; return *this; }
207 #if _LIBCPP_STD_VER >= 20
208 template<sentinel_for
<_Iter
> _Sent
>
209 friend _LIBCPP_HIDE_FROM_ABI
constexpr
210 bool operator==(const move_iterator
& __x
, const move_sentinel
<_Sent
>& __y
)
211 requires __move_iter_comparable
<_Iter
, _Sent
>
213 return __x
.base() == __y
.base();
216 template<sized_sentinel_for
<_Iter
> _Sent
>
217 friend _LIBCPP_HIDE_FROM_ABI
constexpr
218 iter_difference_t
<_Iter
> operator-(const move_sentinel
<_Sent
>& __x
, const move_iterator
& __y
)
220 return __x
.base() - __y
.base();
223 template<sized_sentinel_for
<_Iter
> _Sent
>
224 friend _LIBCPP_HIDE_FROM_ABI
constexpr
225 iter_difference_t
<_Iter
> operator-(const move_iterator
& __x
, const move_sentinel
<_Sent
>& __y
)
227 return __x
.base() - __y
.base();
230 friend _LIBCPP_HIDE_FROM_ABI
constexpr
231 iter_rvalue_reference_t
<_Iter
> iter_move(const move_iterator
& __i
)
232 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
239 void iter_swap(const move_iterator
& __x
, const move_iterator
<_It2
>& __y
)
240 noexcept(noexcept(ranges::iter_swap(__x
.__current_
, __y
.__current_
)))
242 return ranges::iter_swap(__x
.__current_
, __y
.__current_
);
244 #endif // _LIBCPP_STD_VER >= 20
247 template<class _It2
> 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
255 bool operator==(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
257 return __x
.base() == __y
.base();
260 #if _LIBCPP_STD_VER <= 17
261 template <class _Iter1
, class _Iter2
>
262 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
263 bool operator!=(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
265 return __x
.base() != __y
.base();
267 #endif // _LIBCPP_STD_VER <= 17
269 template <class _Iter1
, class _Iter2
>
270 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
271 bool operator<(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
273 return __x
.base() < __y
.base();
276 template <class _Iter1
, class _Iter2
>
277 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
278 bool operator>(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
280 return __x
.base() > __y
.base();
283 template <class _Iter1
, class _Iter2
>
284 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
285 bool operator<=(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
287 return __x
.base() <= __y
.base();
290 template <class _Iter1
, class _Iter2
>
291 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
292 bool operator>=(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
294 return __x
.base() >= __y
.base();
297 #if _LIBCPP_STD_VER >= 20
298 template <class _Iter1
, three_way_comparable_with
<_Iter1
> _Iter2
>
299 inline _LIBCPP_HIDE_FROM_ABI
constexpr
300 auto operator<=>(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
301 -> compare_three_way_result_t
<_Iter1
, _Iter2
>
303 return __x
.base() <=> __y
.base();
305 #endif // _LIBCPP_STD_VER >= 20
307 #ifndef _LIBCPP_CXX03_LANG
308 template <class _Iter1
, class _Iter2
>
309 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
310 auto operator-(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
311 -> decltype(__x
.base() - __y
.base())
313 return __x
.base() - __y
.base();
316 template <class _Iter1
, class _Iter2
>
317 inline _LIBCPP_HIDE_FROM_ABI
318 typename move_iterator
<_Iter1
>::difference_type
319 operator-(const move_iterator
<_Iter1
>& __x
, const move_iterator
<_Iter2
>& __y
)
321 return __x
.base() - __y
.base();
323 #endif // !_LIBCPP_CXX03_LANG
325 #if _LIBCPP_STD_VER >= 20
326 template <class _Iter
>
327 inline _LIBCPP_HIDE_FROM_ABI
constexpr
328 move_iterator
<_Iter
> operator+(iter_difference_t
<_Iter
> __n
, const move_iterator
<_Iter
>& __x
)
329 requires requires
{ { __x
.base() + __n
} -> same_as
<_Iter
>; }
334 template <class _Iter
>
335 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
337 operator+(typename move_iterator
<_Iter
>::difference_type __n
, const move_iterator
<_Iter
>& __x
)
339 return move_iterator
<_Iter
>(__x
.base() + __n
);
341 #endif // _LIBCPP_STD_VER >= 20
343 template <class _Iter
>
344 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
346 make_move_iterator(_Iter __i
)
348 return move_iterator
<_Iter
>(std::move(__i
));
351 _LIBCPP_END_NAMESPACE_STD
355 #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H