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

source code of boost/libs/move/test/conversion_test.cpp