]>
Commit | Line | Data |
---|---|---|
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 | inline 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 |