• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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