1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
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
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___ITERATOR_MOVE_ITERATOR_H
11 #define _LIBCPP___ITERATOR_MOVE_ITERATOR_H
12 
13 #include <__config>
14 #include <__iterator/iterator_traits.h>
15 #include <type_traits>
16 
17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18 #pragma GCC system_header
19 #endif
20 
21 _LIBCPP_BEGIN_NAMESPACE_STD
22 
23 template <class _Iter>
24 class _LIBCPP_TEMPLATE_VIS move_iterator
25 {
26 public:
27 #if _LIBCPP_STD_VER > 17
28     typedef input_iterator_tag iterator_concept;
29 #endif
30 
31     typedef _Iter iterator_type;
32     typedef _If<
33         __is_cpp17_random_access_iterator<_Iter>::value,
34         random_access_iterator_tag,
35         typename iterator_traits<_Iter>::iterator_category
36     >  iterator_category;
37     typedef typename iterator_traits<iterator_type>::value_type value_type;
38     typedef typename iterator_traits<iterator_type>::difference_type difference_type;
39     typedef iterator_type pointer;
40 
41 #ifndef _LIBCPP_CXX03_LANG
42     typedef typename iterator_traits<iterator_type>::reference __reference;
43     typedef typename conditional<
44             is_reference<__reference>::value,
45             typename remove_reference<__reference>::type&&,
46             __reference
47         >::type reference;
48 #else
49     typedef typename iterator_traits<iterator_type>::reference reference;
50 #endif
51 
52     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
53     move_iterator() : __current_() {}
54 
55     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
56     explicit move_iterator(_Iter __i) : __current_(__i) {}
57 
58     template <class _Up, class = __enable_if_t<
59         !is_same<_Up, _Iter>::value && is_convertible<const _Up&, _Iter>::value
60     > >
61     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
62     move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {}
63 
64     template <class _Up, class = __enable_if_t<
65         !is_same<_Up, _Iter>::value &&
66         is_convertible<const _Up&, _Iter>::value &&
67         is_assignable<_Iter&, const _Up&>::value
68     > >
69     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
70     move_iterator& operator=(const move_iterator<_Up>& __u) {
71         __current_ = __u.base();
72         return *this;
73     }
74 
75     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
76     _Iter base() const { return __current_; }
77 
78     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
79     reference operator*() const { return static_cast<reference>(*__current_); }
80     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
81     pointer operator->() const { return __current_; }
82     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
83     reference operator[](difference_type __n) const { return static_cast<reference>(__current_[__n]); }
84 
85     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
86     move_iterator& operator++() { ++__current_; return *this; }
87     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
88     move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; }
89     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
90     move_iterator& operator--() { --__current_; return *this; }
91     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
92     move_iterator operator--(int) { move_iterator __tmp(*this); --__current_; return __tmp; }
93     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
94     move_iterator operator+(difference_type __n) const { return move_iterator(__current_ + __n); }
95     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
96     move_iterator& operator+=(difference_type __n) { __current_ += __n; return *this; }
97     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
98     move_iterator operator-(difference_type __n) const { return move_iterator(__current_ - __n); }
99     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
100     move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; }
101 
102 private:
103     _Iter __current_;
104 };
105 
106 template <class _Iter1, class _Iter2>
107 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
108 bool operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
109 {
110     return __x.base() == __y.base();
111 }
112 
113 template <class _Iter1, class _Iter2>
114 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
115 bool operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
116 {
117     return __x.base() != __y.base();
118 }
119 
120 template <class _Iter1, class _Iter2>
121 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
122 bool operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
123 {
124     return __x.base() < __y.base();
125 }
126 
127 template <class _Iter1, class _Iter2>
128 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
129 bool operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
130 {
131     return __x.base() > __y.base();
132 }
133 
134 template <class _Iter1, class _Iter2>
135 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
136 bool operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
137 {
138     return __x.base() <= __y.base();
139 }
140 
141 template <class _Iter1, class _Iter2>
142 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
143 bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
144 {
145     return __x.base() >= __y.base();
146 }
147 
148 #ifndef _LIBCPP_CXX03_LANG
149 template <class _Iter1, class _Iter2>
150 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
151 auto operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
152     -> decltype(__x.base() - __y.base())
153 {
154     return __x.base() - __y.base();
155 }
156 #else
157 template <class _Iter1, class _Iter2>
158 inline _LIBCPP_HIDE_FROM_ABI
159 typename move_iterator<_Iter1>::difference_type
160 operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y)
161 {
162     return __x.base() - __y.base();
163 }
164 #endif
165 
166 template <class _Iter>
167 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
168 move_iterator<_Iter>
169 operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x)
170 {
171     return move_iterator<_Iter>(__x.base() + __n);
172 }
173 
174 template <class _Iter>
175 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
176 move_iterator<_Iter>
177 make_move_iterator(_Iter __i)
178 {
179     return move_iterator<_Iter>(__i);
180 }
181 
182 _LIBCPP_END_NAMESPACE_STD
183 
184 #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H
185