xref: /freebsd-src/contrib/llvm-project/libcxx/include/__iterator/move_iterator.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric // -*- C++ -*-
2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___ITERATOR_MOVE_ITERATOR_H
11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_MOVE_ITERATOR_H
12fe6060f1SDimitry Andric 
1381ad6265SDimitry Andric #include <__compare/compare_three_way_result.h>
1481ad6265SDimitry Andric #include <__compare/three_way_comparable.h>
1581ad6265SDimitry Andric #include <__concepts/assignable.h>
1681ad6265SDimitry Andric #include <__concepts/convertible_to.h>
1781ad6265SDimitry Andric #include <__concepts/derived_from.h>
1881ad6265SDimitry Andric #include <__concepts/same_as.h>
19fe6060f1SDimitry Andric #include <__config>
2081ad6265SDimitry Andric #include <__iterator/concepts.h>
2181ad6265SDimitry Andric #include <__iterator/incrementable_traits.h>
2281ad6265SDimitry Andric #include <__iterator/iter_move.h>
2381ad6265SDimitry Andric #include <__iterator/iter_swap.h>
24fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h>
2581ad6265SDimitry Andric #include <__iterator/move_sentinel.h>
2681ad6265SDimitry Andric #include <__iterator/readable_traits.h>
27bdd1243dSDimitry Andric #include <__type_traits/conditional.h>
28bdd1243dSDimitry Andric #include <__type_traits/enable_if.h>
29bdd1243dSDimitry Andric #include <__type_traits/is_assignable.h>
30bdd1243dSDimitry Andric #include <__type_traits/is_constructible.h>
31bdd1243dSDimitry Andric #include <__type_traits/is_convertible.h>
32bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
33bdd1243dSDimitry Andric #include <__type_traits/is_same.h>
34bdd1243dSDimitry Andric #include <__type_traits/remove_reference.h>
35bdd1243dSDimitry Andric #include <__utility/declval.h>
3604eeddc0SDimitry Andric #include <__utility/move.h>
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
39fe6060f1SDimitry Andric #  pragma GCC system_header
40fe6060f1SDimitry Andric #endif
41fe6060f1SDimitry Andric 
4206c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
4306c3fb27SDimitry Andric #include <__undef_macros>
4406c3fb27SDimitry Andric 
45fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
46fe6060f1SDimitry Andric 
4706c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
4881ad6265SDimitry Andric template <class _Iter, class = void>
4981ad6265SDimitry Andric struct __move_iter_category_base {};
5081ad6265SDimitry Andric 
5181ad6265SDimitry Andric template <class _Iter>
5281ad6265SDimitry Andric   requires requires { typename iterator_traits<_Iter>::iterator_category; }
5381ad6265SDimitry Andric struct __move_iter_category_base<_Iter> {
54cb14a3feSDimitry Andric   using iterator_category =
55cb14a3feSDimitry Andric       _If< derived_from<typename iterator_traits<_Iter>::iterator_category, random_access_iterator_tag>,
5681ad6265SDimitry Andric            random_access_iterator_tag,
57cb14a3feSDimitry Andric            typename iterator_traits<_Iter>::iterator_category >;
5881ad6265SDimitry Andric };
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric template <class _Iter, class _Sent>
6181ad6265SDimitry Andric concept __move_iter_comparable = requires {
62bdd1243dSDimitry Andric   { std::declval<const _Iter&>() == std::declval<_Sent>() } -> convertible_to<bool>;
6381ad6265SDimitry Andric };
6406c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
6581ad6265SDimitry Andric 
66fe6060f1SDimitry Andric template <class _Iter>
67fe6060f1SDimitry Andric class _LIBCPP_TEMPLATE_VIS move_iterator
6806c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
6981ad6265SDimitry Andric     : public __move_iter_category_base<_Iter>
7081ad6265SDimitry Andric #endif
71fe6060f1SDimitry Andric {
7206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
73cb14a3feSDimitry Andric 
7406c3fb27SDimitry Andric private:
75cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr auto __get_iter_concept() {
7606c3fb27SDimitry Andric     if constexpr (random_access_iterator<_Iter>) {
7706c3fb27SDimitry Andric       return random_access_iterator_tag{};
7806c3fb27SDimitry Andric     } else if constexpr (bidirectional_iterator<_Iter>) {
7906c3fb27SDimitry Andric       return bidirectional_iterator_tag{};
8006c3fb27SDimitry Andric     } else if constexpr (forward_iterator<_Iter>) {
8106c3fb27SDimitry Andric       return forward_iterator_tag{};
8206c3fb27SDimitry Andric     } else {
8306c3fb27SDimitry Andric       return input_iterator_tag{};
8406c3fb27SDimitry Andric     }
8506c3fb27SDimitry Andric   }
8606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
87cb14a3feSDimitry Andric 
88fe6060f1SDimitry Andric public:
8906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
9081ad6265SDimitry Andric   using iterator_type    = _Iter;
9106c3fb27SDimitry Andric   using iterator_concept = decltype(__get_iter_concept());
9281ad6265SDimitry Andric   // iterator_category is inherited and not always present
9381ad6265SDimitry Andric   using value_type      = iter_value_t<_Iter>;
9481ad6265SDimitry Andric   using difference_type = iter_difference_t<_Iter>;
9581ad6265SDimitry Andric   using pointer         = _Iter;
9681ad6265SDimitry Andric   using reference       = iter_rvalue_reference_t<_Iter>;
9781ad6265SDimitry Andric #else
9804eeddc0SDimitry Andric   typedef _Iter iterator_type;
99cb14a3feSDimitry Andric   typedef _If< __has_random_access_iterator_category<_Iter>::value,
10004eeddc0SDimitry Andric                random_access_iterator_tag,
101cb14a3feSDimitry Andric                typename iterator_traits<_Iter>::iterator_category >
102cb14a3feSDimitry Andric       iterator_category;
10304eeddc0SDimitry Andric   typedef typename iterator_traits<iterator_type>::value_type value_type;
10404eeddc0SDimitry Andric   typedef typename iterator_traits<iterator_type>::difference_type difference_type;
10504eeddc0SDimitry Andric   typedef iterator_type pointer;
10604eeddc0SDimitry Andric 
107fe6060f1SDimitry Andric   typedef typename iterator_traits<iterator_type>::reference __reference;
108*0fca6ea1SDimitry Andric   typedef __conditional_t<is_reference<__reference>::value, __libcpp_remove_reference_t<__reference>&&, __reference>
109*0fca6ea1SDimitry Andric       reference;
11006c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
111fe6060f1SDimitry Andric 
112cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {}
11381ad6265SDimitry Andric 
114cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator++() {
115cb14a3feSDimitry Andric     ++__current_;
116cb14a3feSDimitry Andric     return *this;
117cb14a3feSDimitry Andric   }
11881ad6265SDimitry Andric 
119cb14a3feSDimitry Andric   _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer operator->() const {
120cb14a3feSDimitry Andric     return __current_;
121cb14a3feSDimitry Andric   }
12281ad6265SDimitry Andric 
12306c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
124cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr move_iterator()
125cb14a3feSDimitry Andric     requires is_constructible_v<_Iter>
126cb14a3feSDimitry Andric       : __current_() {}
12781ad6265SDimitry Andric 
12881ad6265SDimitry Andric   template <class _Up>
12981ad6265SDimitry Andric     requires(!_IsSame<_Up, _Iter>::value) && convertible_to<const _Up&, _Iter>
130cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {}
13181ad6265SDimitry Andric 
13281ad6265SDimitry Andric   template <class _Up>
133cb14a3feSDimitry Andric     requires(!_IsSame<_Up, _Iter>::value) && convertible_to<const _Up&, _Iter> && assignable_from<_Iter&, const _Up&>
134cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr move_iterator& operator=(const move_iterator<_Up>& __u) {
13581ad6265SDimitry Andric     __current_ = __u.base();
13681ad6265SDimitry Andric     return *this;
13781ad6265SDimitry Andric   }
13881ad6265SDimitry Andric 
13981ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const& noexcept { return __current_; }
14081ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return std::move(__current_); }
14181ad6265SDimitry Andric 
142cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return ranges::iter_move(__current_); }
143cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](difference_type __n) const {
144cb14a3feSDimitry Andric     return ranges::iter_move(__current_ + __n);
14581ad6265SDimitry Andric   }
14681ad6265SDimitry Andric 
147cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(int)
148cb14a3feSDimitry Andric     requires forward_iterator<_Iter>
149cb14a3feSDimitry Andric   {
150cb14a3feSDimitry Andric     move_iterator __tmp(*this);
151cb14a3feSDimitry Andric     ++__current_;
152cb14a3feSDimitry Andric     return __tmp;
153cb14a3feSDimitry Andric   }
154cb14a3feSDimitry Andric 
155cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; }
15681ad6265SDimitry Andric #else
157cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator() : __current_() {}
158fe6060f1SDimitry Andric 
159*0fca6ea1SDimitry Andric   template <class _Up, __enable_if_t< !is_same<_Up, _Iter>::value && is_convertible<const _Up&, _Iter>::value, int> = 0>
160cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator(const move_iterator<_Up>& __u)
161cb14a3feSDimitry Andric       : __current_(__u.base()) {}
162fe6060f1SDimitry Andric 
163cb14a3feSDimitry Andric   template <class _Up,
164*0fca6ea1SDimitry Andric             __enable_if_t< !is_same<_Up, _Iter>::value && is_convertible<const _Up&, _Iter>::value &&
165*0fca6ea1SDimitry Andric                                is_assignable<_Iter&, const _Up&>::value,
166*0fca6ea1SDimitry Andric                            int> = 0>
167cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator=(const move_iterator<_Up>& __u) {
16804eeddc0SDimitry Andric     __current_ = __u.base();
169fe6060f1SDimitry Andric     return *this;
170fe6060f1SDimitry Andric   }
171fe6060f1SDimitry Andric 
172cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Iter base() const { return __current_; }
17304eeddc0SDimitry Andric 
174cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator*() const {
175cb14a3feSDimitry Andric     return static_cast<reference>(*__current_);
176cb14a3feSDimitry Andric   }
177cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](difference_type __n) const {
178cb14a3feSDimitry Andric     return static_cast<reference>(__current_[__n]);
179cb14a3feSDimitry Andric   }
18004eeddc0SDimitry Andric 
181cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator++(int) {
182cb14a3feSDimitry Andric     move_iterator __tmp(*this);
183cb14a3feSDimitry Andric     ++__current_;
184cb14a3feSDimitry Andric     return __tmp;
185cb14a3feSDimitry Andric   }
18606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
18781ad6265SDimitry Andric 
188cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator--() {
189cb14a3feSDimitry Andric     --__current_;
190cb14a3feSDimitry Andric     return *this;
191cb14a3feSDimitry Andric   }
192cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator--(int) {
193cb14a3feSDimitry Andric     move_iterator __tmp(*this);
194cb14a3feSDimitry Andric     --__current_;
195cb14a3feSDimitry Andric     return __tmp;
196cb14a3feSDimitry Andric   }
197cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator+(difference_type __n) const {
198cb14a3feSDimitry Andric     return move_iterator(__current_ + __n);
199cb14a3feSDimitry Andric   }
200cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator+=(difference_type __n) {
201cb14a3feSDimitry Andric     __current_ += __n;
202cb14a3feSDimitry Andric     return *this;
203cb14a3feSDimitry Andric   }
204cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator-(difference_type __n) const {
205cb14a3feSDimitry Andric     return move_iterator(__current_ - __n);
206cb14a3feSDimitry Andric   }
207cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator-=(difference_type __n) {
208cb14a3feSDimitry Andric     __current_ -= __n;
209cb14a3feSDimitry Andric     return *this;
210cb14a3feSDimitry Andric   }
21104eeddc0SDimitry Andric 
21206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
21381ad6265SDimitry Andric   template <sentinel_for<_Iter> _Sent>
214cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y)
21581ad6265SDimitry Andric     requires __move_iter_comparable<_Iter, _Sent>
21681ad6265SDimitry Andric   {
21781ad6265SDimitry Andric     return __x.base() == __y.base();
21881ad6265SDimitry Andric   }
21981ad6265SDimitry Andric 
22081ad6265SDimitry Andric   template <sized_sentinel_for<_Iter> _Sent>
221cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter>
222cb14a3feSDimitry Andric   operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) {
22381ad6265SDimitry Andric     return __x.base() - __y.base();
22481ad6265SDimitry Andric   }
22581ad6265SDimitry Andric 
22681ad6265SDimitry Andric   template <sized_sentinel_for<_Iter> _Sent>
227cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter>
228cb14a3feSDimitry Andric   operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) {
22981ad6265SDimitry Andric     return __x.base() - __y.base();
23081ad6265SDimitry Andric   }
23181ad6265SDimitry Andric 
232cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI constexpr iter_rvalue_reference_t<_Iter>
233cb14a3feSDimitry Andric   iter_move(const move_iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__current_))) {
23481ad6265SDimitry Andric     return ranges::iter_move(__i.__current_);
23581ad6265SDimitry Andric   }
23681ad6265SDimitry Andric 
23781ad6265SDimitry Andric   template <indirectly_swappable<_Iter> _It2>
238cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI constexpr void
239cb14a3feSDimitry Andric   iter_swap(const move_iterator& __x,
240cb14a3feSDimitry Andric             const move_iterator<_It2>& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) {
24181ad6265SDimitry Andric     return ranges::iter_swap(__x.__current_, __y.__current_);
24281ad6265SDimitry Andric   }
24306c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
24481ad6265SDimitry Andric 
24504eeddc0SDimitry Andric private:
246cb14a3feSDimitry Andric   template <class _It2>
247cb14a3feSDimitry Andric   friend class move_iterator;
24881ad6265SDimitry Andric 
24904eeddc0SDimitry Andric   _Iter __current_;
250fe6060f1SDimitry Andric };
251bdd1243dSDimitry Andric _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator);
252fe6060f1SDimitry Andric 
253fe6060f1SDimitry Andric template <class _Iter1, class _Iter2>
254cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool
255cb14a3feSDimitry Andric operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
256fe6060f1SDimitry Andric   return __x.base() == __y.base();
257fe6060f1SDimitry Andric }
258fe6060f1SDimitry Andric 
25981ad6265SDimitry Andric #if _LIBCPP_STD_VER <= 17
260fe6060f1SDimitry Andric template <class _Iter1, class _Iter2>
261cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool
262cb14a3feSDimitry Andric operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
263fe6060f1SDimitry Andric   return __x.base() != __y.base();
264fe6060f1SDimitry Andric }
26581ad6265SDimitry Andric #endif // _LIBCPP_STD_VER <= 17
266fe6060f1SDimitry Andric 
267fe6060f1SDimitry Andric template <class _Iter1, class _Iter2>
268cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool
269cb14a3feSDimitry Andric operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
27004eeddc0SDimitry Andric   return __x.base() < __y.base();
27104eeddc0SDimitry Andric }
27204eeddc0SDimitry Andric 
27304eeddc0SDimitry Andric template <class _Iter1, class _Iter2>
274cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool
275cb14a3feSDimitry Andric operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
276fe6060f1SDimitry Andric   return __x.base() > __y.base();
277fe6060f1SDimitry Andric }
278fe6060f1SDimitry Andric 
279fe6060f1SDimitry Andric template <class _Iter1, class _Iter2>
280cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool
281cb14a3feSDimitry Andric operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
282fe6060f1SDimitry Andric   return __x.base() <= __y.base();
283fe6060f1SDimitry Andric }
284fe6060f1SDimitry Andric 
28504eeddc0SDimitry Andric template <class _Iter1, class _Iter2>
286cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool
287cb14a3feSDimitry Andric operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
28804eeddc0SDimitry Andric   return __x.base() >= __y.base();
28904eeddc0SDimitry Andric }
29004eeddc0SDimitry Andric 
29106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
29281ad6265SDimitry Andric template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2>
293cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr auto
294*0fca6ea1SDimitry Andric operator<=>(const move_iterator<_Iter1>& __x,
295*0fca6ea1SDimitry Andric             const move_iterator<_Iter2>& __y) -> compare_three_way_result_t<_Iter1, _Iter2> {
29681ad6265SDimitry Andric   return __x.base() <=> __y.base();
29781ad6265SDimitry Andric }
29806c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
29981ad6265SDimitry Andric 
300fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG
301fe6060f1SDimitry Andric template <class _Iter1, class _Iter2>
302cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto
303cb14a3feSDimitry Andric operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -> decltype(__x.base() - __y.base()) {
304fe6060f1SDimitry Andric   return __x.base() - __y.base();
305fe6060f1SDimitry Andric }
306fe6060f1SDimitry Andric #else
307fe6060f1SDimitry Andric template <class _Iter1, class _Iter2>
308cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI typename move_iterator<_Iter1>::difference_type
309cb14a3feSDimitry Andric operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {
310fe6060f1SDimitry Andric   return __x.base() - __y.base();
311fe6060f1SDimitry Andric }
31281ad6265SDimitry Andric #endif // !_LIBCPP_CXX03_LANG
313fe6060f1SDimitry Andric 
31406c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
31581ad6265SDimitry Andric template <class _Iter>
316cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iter>
317cb14a3feSDimitry Andric operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x)
318cb14a3feSDimitry Andric   requires requires {
319cb14a3feSDimitry Andric     { __x.base() + __n } -> same_as<_Iter>;
320cb14a3feSDimitry Andric   }
32181ad6265SDimitry Andric {
32281ad6265SDimitry Andric   return __x + __n;
32381ad6265SDimitry Andric }
32481ad6265SDimitry Andric #else
325fe6060f1SDimitry Andric template <class _Iter>
326cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter>
327cb14a3feSDimitry Andric operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) {
328fe6060f1SDimitry Andric   return move_iterator<_Iter>(__x.base() + __n);
329fe6060f1SDimitry Andric }
33006c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
331fe6060f1SDimitry Andric 
332*0fca6ea1SDimitry Andric #if _LIBCPP_STD_VER >= 20
333*0fca6ea1SDimitry Andric template <class _Iter1, class _Iter2>
334*0fca6ea1SDimitry Andric   requires(!sized_sentinel_for<_Iter1, _Iter2>)
335*0fca6ea1SDimitry Andric inline constexpr bool disable_sized_sentinel_for<move_iterator<_Iter1>, move_iterator<_Iter2>> = true;
336*0fca6ea1SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
337*0fca6ea1SDimitry Andric 
338fe6060f1SDimitry Andric template <class _Iter>
339cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter> make_move_iterator(_Iter __i) {
34081ad6265SDimitry Andric   return move_iterator<_Iter>(std::move(__i));
341fe6060f1SDimitry Andric }
342fe6060f1SDimitry Andric 
343fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
344fe6060f1SDimitry Andric 
34506c3fb27SDimitry Andric _LIBCPP_POP_MACROS
34606c3fb27SDimitry Andric 
347fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H
348