1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2010-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 #include <boost/move/utility_core.hpp>
12 #include <boost/move/detail/meta_utils.hpp>
13 #include <cassert>
14 #include <new>
15 #include <boost/move/detail/move_helpers.hpp>
16
17
18 enum ConstructionType { Copied, Moved, Other };
19
20 class conversion_source
21 {
22 public:
conversion_source()23 conversion_source(){}
operator int() const24 operator int() const { return 0; }
25 };
26
27 class conversion_target
28 {
29 ConstructionType c_type_;
30 public:
conversion_target(conversion_source)31 conversion_target(conversion_source)
32 { c_type_ = Other; }
conversion_target()33 conversion_target()
34 { c_type_ = Other; }
conversion_target(const conversion_target &)35 conversion_target(const conversion_target &)
36 { c_type_ = Copied; }
construction_type() const37 ConstructionType construction_type() const
38 { return c_type_; }
39 };
40
41
42 class conversion_target_copymovable
43 {
44 ConstructionType c_type_;
45 BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable)
46 public:
conversion_target_copymovable()47 conversion_target_copymovable()
48 { c_type_ = Other; }
conversion_target_copymovable(conversion_source)49 conversion_target_copymovable(conversion_source)
50 { c_type_ = Other; }
conversion_target_copymovable(const conversion_target_copymovable &)51 conversion_target_copymovable(const conversion_target_copymovable &)
52 { c_type_ = Copied; }
conversion_target_copymovable(BOOST_RV_REF (conversion_target_copymovable))53 conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) )
54 { c_type_ = Moved; }
operator =(BOOST_RV_REF (conversion_target_copymovable))55 conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) )
56 { c_type_ = Moved; return *this; }
operator =(BOOST_COPY_ASSIGN_REF (conversion_target_copymovable))57 conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) )
58 { c_type_ = Copied; return *this; }
construction_type() const59 ConstructionType construction_type() const
60 { return c_type_; }
61 };
62
63 class conversion_target_movable
64 {
65 ConstructionType c_type_;
66 BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable)
67 public:
conversion_target_movable()68 conversion_target_movable()
69 { c_type_ = Other; }
conversion_target_movable(conversion_source)70 conversion_target_movable(conversion_source)
71 { c_type_ = Other; }
conversion_target_movable(BOOST_RV_REF (conversion_target_movable))72 conversion_target_movable(BOOST_RV_REF(conversion_target_movable) )
73 { c_type_ = Moved; }
operator =(BOOST_RV_REF (conversion_target_movable))74 conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) )
75 { c_type_ = Moved; return *this; }
construction_type() const76 ConstructionType construction_type() const
77 { return c_type_; }
78 };
79
80
81 template<class T>
82 class container
83 {
84 T *storage_;
85 public:
86 struct const_iterator{};
87 struct iterator : const_iterator{};
container()88 container()
89 : storage_(0)
90 {}
91
~container()92 ~container()
93 { delete storage_; }
94
container(const container & c)95 container(const container &c)
96 : storage_(c.storage_ ? new T(*c.storage_) : 0)
97 {}
98
operator =(const container & c)99 container &operator=(const container &c)
100 {
101 if(storage_){
102 delete storage_;
103 storage_ = 0;
104 }
105 storage_ = c.storage_ ? new T(*c.storage_) : 0;
106 return *this;
107 }
108
BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back,T,void,priv_push_back)109 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
110
111 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
112
113 template <class Iterator>
114 iterator insert(Iterator, Iterator){ return iterator(); }
115
construction_type() const116 ConstructionType construction_type() const
117 { return construction_type_impl
118 (typename ::boost::move_detail::integral_constant<bool, ::boost::move_detail::is_class_or_union<T>::value>());
119 }
120
construction_type_impl(::boost::move_detail::true_type) const121 ConstructionType construction_type_impl(::boost::move_detail::true_type) const
122 { return storage_->construction_type(); }
123
construction_type_impl(::boost::move_detail::false_type) const124 ConstructionType construction_type_impl(::boost::move_detail::false_type) const
125 { return Copied; }
126
begin() const127 iterator begin() const { return iterator(); }
128
129 private:
130 template<class U>
priv_construct(BOOST_MOVE_CATCH_FWD (U)x)131 void priv_construct(BOOST_MOVE_CATCH_FWD(U) x)
132 {
133 if(storage_){
134 delete storage_;
135 storage_ = 0;
136 }
137 storage_ = new T(::boost::forward<U>(x));
138 }
139
140 template<class U>
priv_push_back(BOOST_MOVE_CATCH_FWD (U)x)141 void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
142 { priv_construct(::boost::forward<U>(x)); }
143
144 template<class U>
priv_insert(const_iterator,BOOST_MOVE_CATCH_FWD (U)x)145 iterator priv_insert(const_iterator, BOOST_MOVE_CATCH_FWD(U) x)
146 { priv_construct(::boost::forward<U>(x)); return iterator(); }
147 };
148
149 class recursive_container
150 {
151 BOOST_COPYABLE_AND_MOVABLE(recursive_container)
152 public:
recursive_container()153 recursive_container()
154 {}
155
recursive_container(const recursive_container & c)156 recursive_container(const recursive_container &c)
157 : container_(c.container_)
158 {}
159
recursive_container(BOOST_RV_REF (recursive_container)c)160 recursive_container(BOOST_RV_REF(recursive_container) c)
161 : container_(::boost::move(c.container_))
162 {}
163
operator =(BOOST_COPY_ASSIGN_REF (recursive_container)c)164 recursive_container & operator =(BOOST_COPY_ASSIGN_REF(recursive_container) c)
165 {
166 container_= c.container_;
167 return *this;
168 }
169
operator =(BOOST_RV_REF (recursive_container)c)170 recursive_container & operator =(BOOST_RV_REF(recursive_container) c)
171 {
172 container_= ::boost::move(c.container_);
173 return *this;
174 }
175
176 container<recursive_container> container_;
operator <(const recursive_container & a,const recursive_container & b)177 friend bool operator< (const recursive_container &a, const recursive_container &b)
178 { return &a < &b; }
179 };
180
181
main()182 int main()
183 {
184 conversion_target_movable a;
185 conversion_target_movable b(::boost::move(a));
186 {
187 container<conversion_target> c;
188 {
189 conversion_target x;
190 c.push_back(x);
191 assert(c.construction_type() == Copied);
192 c.insert(c.begin(), x);
193 assert(c.construction_type() == Copied);
194 }
195 {
196 const conversion_target x;
197 c.push_back(x);
198 assert(c.construction_type() == Copied);
199 c.insert(c.begin(), x);
200 assert(c.construction_type() == Copied);
201 }
202 {
203 c.push_back(conversion_target());
204 assert(c.construction_type() == Copied);
205 c.insert(c.begin(), conversion_target());
206 assert(c.construction_type() == Copied);
207 }
208 {
209 conversion_source x;
210 c.push_back(x);
211 assert(c.construction_type() == Copied);
212 c.insert(c.begin(), x);
213 assert(c.construction_type() == Copied);
214 }
215 {
216 const conversion_source x;
217 c.push_back(x);
218 assert(c.construction_type() == Copied);
219 c.insert(c.begin(), x);
220 assert(c.construction_type() == Copied);
221 }
222 {
223 c.push_back(conversion_source());
224 assert(c.construction_type() == Copied);
225 c.insert(c.begin(), conversion_source());
226 assert(c.construction_type() == Copied);
227 }
228 }
229
230 {
231 container<conversion_target_copymovable> c;
232 {
233 conversion_target_copymovable x;
234 c.push_back(x);
235 assert(c.construction_type() == Copied);
236 c.insert(c.begin(), x);
237 assert(c.construction_type() == Copied);
238 }
239 {
240 const conversion_target_copymovable x;
241 c.push_back(x);
242 assert(c.construction_type() == Copied);
243 c.insert(c.begin(), x);
244 assert(c.construction_type() == Copied);
245 }
246 {
247 c.push_back(conversion_target_copymovable());
248 assert(c.construction_type() == Moved);
249 c.insert(c.begin(), conversion_target_copymovable());
250 assert(c.construction_type() == Moved);
251 }
252 {
253 conversion_source x;
254 c.push_back(x);
255 assert(c.construction_type() == Moved);
256 c.insert(c.begin(), x);
257 assert(c.construction_type() == Moved);
258 }
259 {
260 const conversion_source x;
261 c.push_back(x);
262 assert(c.construction_type() == Moved);
263 c.insert(c.begin(), x);
264 assert(c.construction_type() == Moved);
265 }
266 {
267 c.push_back(conversion_source());
268 assert(c.construction_type() == Moved);
269 c.insert(c.begin(), conversion_source());
270 assert(c.construction_type() == Moved);
271 }
272 }
273 {
274 container<conversion_target_movable> c;
275 //This should not compile
276 //{
277 // conversion_target_movable x;
278 // c.push_back(x);
279 // assert(c.construction_type() == Copied);
280 //}
281 //{
282 // const conversion_target_movable x;
283 // c.push_back(x);
284 // assert(c.construction_type() == Copied);
285 //}
286 {
287 c.push_back(conversion_target_movable());
288 assert(c.construction_type() == Moved);
289 c.insert(c.begin(), conversion_target_movable());
290 assert(c.construction_type() == Moved);
291 }
292 {
293 conversion_source x;
294 c.push_back(x);
295 assert(c.construction_type() == Moved);
296 c.insert(c.begin(), x);
297 assert(c.construction_type() == Moved);
298 }
299 {
300 const conversion_source x;
301 c.push_back(x);
302 assert(c.construction_type() == Moved);
303 c.insert(c.begin(), x);
304 assert(c.construction_type() == Moved);
305 }
306 {
307 c.push_back(conversion_source());
308 assert(c.construction_type() == Moved);
309 c.insert(c.begin(), conversion_source());
310 assert(c.construction_type() == Moved);
311 }
312 }
313 {
314 container<int> c;
315 {
316 int x = 0;
317 c.push_back(x);
318 assert(c.construction_type() == Copied);
319 c.insert(c.begin(), c.construction_type());
320 assert(c.construction_type() == Copied);
321 }
322 {
323 const int x = 0;
324 c.push_back(x);
325 assert(c.construction_type() == Copied);
326 c.insert(c.begin(), x);
327 assert(c.construction_type() == Copied);
328 }
329 {
330 c.push_back(int(0));
331 assert(c.construction_type() == Copied);
332 c.insert(c.begin(), int(0));
333 assert(c.construction_type() == Copied);
334 }
335 {
336 conversion_source x;
337 c.push_back(x);
338 assert(c.construction_type() == Copied);
339 c.insert(c.begin(), x);
340 assert(c.construction_type() == Copied);
341 }
342
343 {
344 const conversion_source x;
345 c.push_back(x);
346 assert(c.construction_type() == Copied);
347 c.insert(c.begin(), x);
348 assert(c.construction_type() == Copied);
349 }
350 {
351 c.push_back(conversion_source());
352 assert(c.construction_type() == Copied);
353 c.insert(c.begin(), conversion_source());
354 assert(c.construction_type() == Copied);
355 }
356 //c.insert(c.begin(), c.begin());
357 }
358
359 {
360 container<int> c;
361 {
362 int x = 0;
363 c.push_back(x);
364 assert(c.construction_type() == Copied);
365 c.insert(c.begin(), c.construction_type());
366 assert(c.construction_type() == Copied);
367 }
368 {
369 const int x = 0;
370 c.push_back(x);
371 assert(c.construction_type() == Copied);
372 c.insert(c.begin(), x);
373 assert(c.construction_type() == Copied);
374 }
375 {
376 c.push_back(int(0));
377 assert(c.construction_type() == Copied);
378 c.insert(c.begin(), int(0));
379 assert(c.construction_type() == Copied);
380 }
381 {
382 conversion_source x;
383 c.push_back(x);
384 assert(c.construction_type() == Copied);
385 c.insert(c.begin(), x);
386 assert(c.construction_type() == Copied);
387 }
388
389 {
390 const conversion_source x;
391 c.push_back(x);
392 assert(c.construction_type() == Copied);
393 c.insert(c.begin(), x);
394 assert(c.construction_type() == Copied);
395 }
396 {
397 c.push_back(conversion_source());
398 assert(c.construction_type() == Copied);
399 c.insert(c.begin(), conversion_source());
400 assert(c.construction_type() == Copied);
401 }
402 c.insert(c.begin(), c.begin());
403 }
404
405 {
406 recursive_container c;
407 recursive_container internal;
408 c.container_.insert(c.container_.begin(), recursive_container());
409 c.container_.insert(c.container_.begin(), internal);
410 c.container_.insert(c.container_.begin(), c.container_.begin());
411 }
412
413 return 0;
414 }
415