blob: 8e901f871b81c4aff5ee0e504dd991c651b09390 [file] [log] [blame]
Brian Silverman1f5d3982018-08-04 23:37:52 -07001//////////////////////////////////////////////////////////////////////////////
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
18enum ConstructionType { Copied, Moved, Other };
19
20class conversion_source
21{
22 public:
23 conversion_source(){}
24 operator int() const { return 0; }
25};
26
27class conversion_target
28{
29 ConstructionType c_type_;
30 public:
31 conversion_target(conversion_source)
32 { c_type_ = Other; }
33 conversion_target()
34 { c_type_ = Other; }
35 conversion_target(const conversion_target &)
36 { c_type_ = Copied; }
37 ConstructionType construction_type() const
38 { return c_type_; }
39};
40
41
42class conversion_target_copymovable
43{
44 ConstructionType c_type_;
45 BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable)
46 public:
47 conversion_target_copymovable()
48 { c_type_ = Other; }
49 conversion_target_copymovable(conversion_source)
50 { c_type_ = Other; }
51 conversion_target_copymovable(const conversion_target_copymovable &)
52 { c_type_ = Copied; }
53 conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) )
54 { c_type_ = Moved; }
55 conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) )
56 { c_type_ = Moved; return *this; }
57 conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) )
58 { c_type_ = Copied; return *this; }
59 ConstructionType construction_type() const
60 { return c_type_; }
61};
62
63class conversion_target_movable
64{
65 ConstructionType c_type_;
66 BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable)
67 public:
68 conversion_target_movable()
69 { c_type_ = Other; }
70 conversion_target_movable(conversion_source)
71 { c_type_ = Other; }
72 conversion_target_movable(BOOST_RV_REF(conversion_target_movable) )
73 { c_type_ = Moved; }
74 conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) )
75 { c_type_ = Moved; return *this; }
76 ConstructionType construction_type() const
77 { return c_type_; }
78};
79
80
81template<class T>
82class container
83{
84 T *storage_;
85 public:
86 struct const_iterator{};
87 struct iterator : const_iterator{};
88 container()
89 : storage_(0)
90 {}
91
92 ~container()
93 { delete storage_; }
94
95 container(const container &c)
96 : storage_(c.storage_ ? new T(*c.storage_) : 0)
97 {}
98
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
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
116 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
121 ConstructionType construction_type_impl(::boost::move_detail::true_type) const
122 { return storage_->construction_type(); }
123
124 ConstructionType construction_type_impl(::boost::move_detail::false_type) const
125 { return Copied; }
126
127 iterator begin() const { return iterator(); }
128
129 private:
130 template<class U>
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>
141 void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
142 { priv_construct(::boost::forward<U>(x)); }
143
144 template<class U>
145 iterator priv_insert(const_iterator, BOOST_MOVE_CATCH_FWD(U) x)
146 { priv_construct(::boost::forward<U>(x)); return iterator(); }
147};
148
149class recursive_container
150{
151 BOOST_COPYABLE_AND_MOVABLE(recursive_container)
152 public:
153 recursive_container()
154 {}
155
156 recursive_container(const recursive_container &c)
157 : container_(c.container_)
158 {}
159
160 recursive_container(BOOST_RV_REF(recursive_container) c)
161 : container_(::boost::move(c.container_))
162 {}
163
164 recursive_container & operator =(BOOST_COPY_ASSIGN_REF(recursive_container) c)
165 {
166 container_= c.container_;
167 return *this;
168 }
169
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_;
177 friend bool operator< (const recursive_container &a, const recursive_container &b)
178 { return &a < &b; }
179};
180
181
182int 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}