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