1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2012-2012. |
4 | // Distributed under the Boost Software License, Version 1.0. |
5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | // |
8 | // See http://www.boost.org/libs/move for documentation. |
9 | // |
10 | ////////////////////////////////////////////////////////////////////////////// |
11 | |
12 | //! \file |
13 | |
14 | #ifndef BOOST_MOVE_ITERATOR_HPP |
15 | #define BOOST_MOVE_ITERATOR_HPP |
16 | |
17 | #ifndef BOOST_CONFIG_HPP |
18 | # include <boost/config.hpp> |
19 | #endif |
20 | # |
21 | #if defined(BOOST_HAS_PRAGMA_ONCE) |
22 | # pragma once |
23 | #endif |
24 | |
25 | #include <boost/move/detail/config_begin.hpp> |
26 | #include <boost/move/detail/workaround.hpp> //forceinline |
27 | #include <boost/move/detail/iterator_traits.hpp> |
28 | #include <boost/move/utility_core.hpp> |
29 | |
30 | namespace boost { |
31 | |
32 | ////////////////////////////////////////////////////////////////////////////// |
33 | // |
34 | // move_iterator |
35 | // |
36 | ////////////////////////////////////////////////////////////////////////////// |
37 | |
38 | //! Class template move_iterator is an iterator adaptor with the same behavior |
39 | //! as the underlying iterator except that its dereference operator implicitly |
40 | //! converts the value returned by the underlying iterator's dereference operator |
41 | //! to an rvalue reference. Some generic algorithms can be called with move |
42 | //! iterators to replace copying with moving. |
43 | template <class It> |
44 | class move_iterator |
45 | { |
46 | public: |
47 | typedef It iterator_type; |
48 | typedef typename boost::movelib::iterator_traits<iterator_type>::value_type value_type; |
49 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_DOXYGEN_INVOKED) |
50 | typedef value_type && reference; |
51 | #else |
52 | typedef typename ::boost::move_detail::if_ |
53 | < ::boost::has_move_emulation_enabled<value_type> |
54 | , ::boost::rv<value_type>& |
55 | , value_type & >::type reference; |
56 | #endif |
57 | typedef It pointer; |
58 | typedef typename boost::movelib::iterator_traits<iterator_type>::difference_type difference_type; |
59 | typedef typename boost::movelib::iterator_traits<iterator_type>::iterator_category iterator_category; |
60 | |
61 | BOOST_MOVE_FORCEINLINE move_iterator() |
62 | : m_it() |
63 | {} |
64 | |
65 | BOOST_MOVE_FORCEINLINE explicit move_iterator(const It &i) |
66 | : m_it(i) |
67 | {} |
68 | |
69 | template <class U> |
70 | BOOST_MOVE_FORCEINLINE move_iterator(const move_iterator<U>& u) |
71 | : m_it(u.m_it) |
72 | {} |
73 | |
74 | BOOST_MOVE_FORCEINLINE reference operator*() const |
75 | { |
76 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) |
77 | return *m_it; |
78 | #else |
79 | return ::boost::move(*m_it); |
80 | #endif |
81 | } |
82 | |
83 | BOOST_MOVE_FORCEINLINE pointer operator->() const |
84 | { return m_it; } |
85 | |
86 | BOOST_MOVE_FORCEINLINE move_iterator& operator++() |
87 | { ++m_it; return *this; } |
88 | |
89 | BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator++(int) |
90 | { move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; } |
91 | |
92 | BOOST_MOVE_FORCEINLINE move_iterator& operator--() |
93 | { --m_it; return *this; } |
94 | |
95 | BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator--(int) |
96 | { move_iterator<iterator_type> tmp(*this); --(*this); return tmp; } |
97 | |
98 | move_iterator<iterator_type> operator+ (difference_type n) const |
99 | { return move_iterator<iterator_type>(m_it + n); } |
100 | |
101 | BOOST_MOVE_FORCEINLINE move_iterator& operator+=(difference_type n) |
102 | { m_it += n; return *this; } |
103 | |
104 | BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator- (difference_type n) const |
105 | { return move_iterator<iterator_type>(m_it - n); } |
106 | |
107 | BOOST_MOVE_FORCEINLINE move_iterator& operator-=(difference_type n) |
108 | { m_it -= n; return *this; } |
109 | |
110 | BOOST_MOVE_FORCEINLINE reference operator[](difference_type n) const |
111 | { |
112 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) |
113 | return m_it[n]; |
114 | #else |
115 | return ::boost::move(m_it[n]); |
116 | #endif |
117 | } |
118 | |
119 | BOOST_MOVE_FORCEINLINE friend bool operator==(const move_iterator& x, const move_iterator& y) |
120 | { return x.m_it == y.m_it; } |
121 | |
122 | BOOST_MOVE_FORCEINLINE friend bool operator!=(const move_iterator& x, const move_iterator& y) |
123 | { return x.m_it != y.m_it; } |
124 | |
125 | BOOST_MOVE_FORCEINLINE friend bool operator< (const move_iterator& x, const move_iterator& y) |
126 | { return x.m_it < y.m_it; } |
127 | |
128 | BOOST_MOVE_FORCEINLINE friend bool operator<=(const move_iterator& x, const move_iterator& y) |
129 | { return x.m_it <= y.m_it; } |
130 | |
131 | BOOST_MOVE_FORCEINLINE friend bool operator> (const move_iterator& x, const move_iterator& y) |
132 | { return x.m_it > y.m_it; } |
133 | |
134 | BOOST_MOVE_FORCEINLINE friend bool operator>=(const move_iterator& x, const move_iterator& y) |
135 | { return x.m_it >= y.m_it; } |
136 | |
137 | BOOST_MOVE_FORCEINLINE friend difference_type operator-(const move_iterator& x, const move_iterator& y) |
138 | { return x.m_it - y.m_it; } |
139 | |
140 | BOOST_MOVE_FORCEINLINE friend move_iterator operator+(difference_type n, const move_iterator& x) |
141 | { return move_iterator(x.m_it + n); } |
142 | |
143 | private: |
144 | It m_it; |
145 | }; |
146 | |
147 | //is_move_iterator |
148 | namespace move_detail { |
149 | |
150 | template <class I> |
151 | struct is_move_iterator |
152 | { |
153 | static const bool value = false; |
154 | }; |
155 | |
156 | template <class I> |
157 | struct is_move_iterator< ::boost::move_iterator<I> > |
158 | { |
159 | static const bool value = true; |
160 | }; |
161 | |
162 | } //namespace move_detail { |
163 | |
164 | ////////////////////////////////////////////////////////////////////////////// |
165 | // |
166 | // move_iterator |
167 | // |
168 | ////////////////////////////////////////////////////////////////////////////// |
169 | |
170 | //! |
171 | //! <b>Returns</b>: move_iterator<It>(i). |
172 | template<class It> |
173 | BOOST_MOVE_FORCEINLINE move_iterator<It> make_move_iterator(const It &it) |
174 | { return move_iterator<It>(it); } |
175 | |
176 | ////////////////////////////////////////////////////////////////////////////// |
177 | // |
178 | // back_move_insert_iterator |
179 | // |
180 | ////////////////////////////////////////////////////////////////////////////// |
181 | |
182 | |
183 | //! A move insert iterator that move constructs elements at the |
184 | //! back of a container |
185 | template <typename C> // C models Container |
186 | class back_move_insert_iterator |
187 | { |
188 | C* container_m; |
189 | |
190 | public: |
191 | typedef C container_type; |
192 | typedef typename C::value_type value_type; |
193 | typedef typename C::reference reference; |
194 | typedef typename C::pointer pointer; |
195 | typedef typename C::difference_type difference_type; |
196 | typedef std::output_iterator_tag iterator_category; |
197 | |
198 | explicit back_move_insert_iterator(C& x) : container_m(&x) { } |
199 | |
200 | back_move_insert_iterator& operator=(reference x) |
201 | { container_m->push_back(boost::move(x)); return *this; } |
202 | |
203 | back_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) |
204 | { reference rx = x; return this->operator=(rx); } |
205 | |
206 | back_move_insert_iterator& operator*() { return *this; } |
207 | back_move_insert_iterator& operator++() { return *this; } |
208 | back_move_insert_iterator& operator++(int) { return *this; } |
209 | }; |
210 | |
211 | //! |
212 | //! <b>Returns</b>: back_move_insert_iterator<C>(x). |
213 | template <typename C> // C models Container |
214 | inline back_move_insert_iterator<C> back_move_inserter(C& x) |
215 | { |
216 | return back_move_insert_iterator<C>(x); |
217 | } |
218 | |
219 | ////////////////////////////////////////////////////////////////////////////// |
220 | // |
221 | // front_move_insert_iterator |
222 | // |
223 | ////////////////////////////////////////////////////////////////////////////// |
224 | |
225 | //! A move insert iterator that move constructs elements int the |
226 | //! front of a container |
227 | template <typename C> // C models Container |
228 | class front_move_insert_iterator |
229 | { |
230 | C* container_m; |
231 | |
232 | public: |
233 | typedef C container_type; |
234 | typedef typename C::value_type value_type; |
235 | typedef typename C::reference reference; |
236 | typedef typename C::pointer pointer; |
237 | typedef typename C::difference_type difference_type; |
238 | typedef std::output_iterator_tag iterator_category; |
239 | |
240 | explicit front_move_insert_iterator(C& x) : container_m(&x) { } |
241 | |
242 | front_move_insert_iterator& operator=(reference x) |
243 | { container_m->push_front(boost::move(x)); return *this; } |
244 | |
245 | front_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) |
246 | { reference rx = x; return this->operator=(rx); } |
247 | |
248 | front_move_insert_iterator& operator*() { return *this; } |
249 | front_move_insert_iterator& operator++() { return *this; } |
250 | front_move_insert_iterator& operator++(int) { return *this; } |
251 | }; |
252 | |
253 | //! |
254 | //! <b>Returns</b>: front_move_insert_iterator<C>(x). |
255 | template <typename C> // C models Container |
256 | inline front_move_insert_iterator<C> front_move_inserter(C& x) |
257 | { |
258 | return front_move_insert_iterator<C>(x); |
259 | } |
260 | |
261 | ////////////////////////////////////////////////////////////////////////////// |
262 | // |
263 | // insert_move_iterator |
264 | // |
265 | ////////////////////////////////////////////////////////////////////////////// |
266 | template <typename C> // C models Container |
267 | class move_insert_iterator |
268 | { |
269 | C* container_m; |
270 | typename C::iterator pos_; |
271 | |
272 | public: |
273 | typedef C container_type; |
274 | typedef typename C::value_type value_type; |
275 | typedef typename C::reference reference; |
276 | typedef typename C::pointer pointer; |
277 | typedef typename C::difference_type difference_type; |
278 | typedef std::output_iterator_tag iterator_category; |
279 | |
280 | explicit move_insert_iterator(C& x, typename C::iterator pos) |
281 | : container_m(&x), pos_(pos) |
282 | {} |
283 | |
284 | move_insert_iterator& operator=(reference x) |
285 | { |
286 | pos_ = container_m->insert(pos_, ::boost::move(x)); |
287 | ++pos_; |
288 | return *this; |
289 | } |
290 | |
291 | move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) |
292 | { reference rx = x; return this->operator=(rx); } |
293 | |
294 | move_insert_iterator& operator*() { return *this; } |
295 | move_insert_iterator& operator++() { return *this; } |
296 | move_insert_iterator& operator++(int) { return *this; } |
297 | }; |
298 | |
299 | //! |
300 | //! <b>Returns</b>: move_insert_iterator<C>(x, it). |
301 | template <typename C> // C models Container |
302 | inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it) |
303 | { |
304 | return move_insert_iterator<C>(x, it); |
305 | } |
306 | |
307 | } //namespace boost { |
308 | |
309 | #include <boost/move/detail/config_end.hpp> |
310 | |
311 | #endif //#ifndef BOOST_MOVE_ITERATOR_HPP |
312 | |