1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2009.
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/detail/config_begin.hpp>
12 #include <boost/move/utility_core.hpp>
13 
14 //[clone_ptr_base_derived
15 class Base
16 {
17    BOOST_COPYABLE_AND_MOVABLE(Base)
18 
19    public:
Base()20    Base(){}
21 
Base(const Base &)22    Base(const Base &/*x*/) {/**/}            // Copy ctor
23 
Base(BOOST_RV_REF (Base))24    Base(BOOST_RV_REF(Base) /*x*/) {/**/}     // Move ctor
25 
operator =(BOOST_RV_REF (Base))26    Base& operator=(BOOST_RV_REF(Base) /*x*/)
27    {/**/ return *this;}                      // Move assign
28 
operator =(BOOST_COPY_ASSIGN_REF (Base))29    Base& operator=(BOOST_COPY_ASSIGN_REF(Base) /*x*/)
30    {/**/ return *this;}                      // Copy assign
31 
clone() const32    virtual Base *clone() const
33    {  return new Base(*this);  }
34 
~Base()35    virtual ~Base(){}
36 };
37 
38 class Member
39 {
40    BOOST_COPYABLE_AND_MOVABLE(Member)
41 
42    public:
Member()43    Member(){}
44 
45    // Compiler-generated copy constructor...
46 
Member(BOOST_RV_REF (Member))47    Member(BOOST_RV_REF(Member))  {/**/}      // Move ctor
48 
operator =(BOOST_RV_REF (Member))49    Member &operator=(BOOST_RV_REF(Member))   // Move assign
50    {/**/ return *this;  }
51 
operator =(BOOST_COPY_ASSIGN_REF (Member))52    Member &operator=(BOOST_COPY_ASSIGN_REF(Member))   // Copy assign
53    {/**/ return *this;  }
54 };
55 
56 class Derived : public Base
57 {
58    BOOST_COPYABLE_AND_MOVABLE(Derived)
59    Member mem_;
60 
61    public:
Derived()62    Derived(){}
63 
64    // Compiler-generated copy constructor...
65 
Derived(BOOST_RV_REF (Derived)x)66    Derived(BOOST_RV_REF(Derived) x)             // Move ctor
67       : Base(BOOST_MOVE_BASE(Base, x)),
68         mem_(boost::move(x.mem_)) { }
69 
operator =(BOOST_RV_REF (Derived)x)70    Derived& operator=(BOOST_RV_REF(Derived) x)  // Move assign
71    {
72       Base::operator=(BOOST_MOVE_BASE(Base, x));
73       mem_ = boost::move(x.mem_);
74       return *this;
75    }
76 
operator =(BOOST_COPY_ASSIGN_REF (Derived)x)77    Derived& operator=(BOOST_COPY_ASSIGN_REF(Derived) x)  // Copy assign
78    {
79       Base::operator=(x);
80       mem_  = x.mem_;
81       return *this;
82    }
83    // ...
84 };
85 //]
86 
87 //[clone_ptr_def
88 template <class T>
89 class clone_ptr
90 {
91    private:
92    // Mark this class copyable and movable
93    BOOST_COPYABLE_AND_MOVABLE(clone_ptr)
94    T* ptr;
95 
96    public:
97    // Construction
clone_ptr(T * p=0)98    explicit clone_ptr(T* p = 0) : ptr(p) {}
99 
100    // Destruction
~clone_ptr()101    ~clone_ptr() { delete ptr; }
102 
clone_ptr(const clone_ptr & p)103    clone_ptr(const clone_ptr& p) // Copy constructor (as usual)
104       : ptr(p.ptr ? p.ptr->clone() : 0) {}
105 
operator =(BOOST_COPY_ASSIGN_REF (clone_ptr)p)106    clone_ptr& operator=(BOOST_COPY_ASSIGN_REF(clone_ptr) p) // Copy assignment
107    {
108       if (this != &p){
109          T *tmp_p = p.ptr ? p.ptr->clone() : 0;
110          delete ptr;
111          ptr = tmp_p;
112       }
113       return *this;
114    }
115 
116    //Move semantics...
clone_ptr(BOOST_RV_REF (clone_ptr)p)117    clone_ptr(BOOST_RV_REF(clone_ptr) p)            //Move constructor
118       : ptr(p.ptr) { p.ptr = 0; }
119 
operator =(BOOST_RV_REF (clone_ptr)p)120    clone_ptr& operator=(BOOST_RV_REF(clone_ptr) p) //Move assignment
121    {
122       if (this != &p){
123          delete ptr;
124          ptr = p.ptr;
125          p.ptr = 0;
126       }
127       return *this;
128    }
129 };
130 //]
131 
main()132 int main()
133 {
134    {
135    //[copy_clone_ptr
136    clone_ptr<Base> p1(new Derived());
137    // ...
138    clone_ptr<Base> p2 = p1;  // p2 and p1 each own their own pointer
139    //]
140    }
141    {
142    //[move_clone_ptr
143    clone_ptr<Base> p1(new Derived());
144    // ...
145    clone_ptr<Base> p2 = boost::move(p1);  // p2 now owns the pointer instead of p1
146    p2 = clone_ptr<Base>(new Derived());   // temporary is moved to p2
147    }
148    //]
149    //[clone_ptr_move_derived
150    Derived d;
151    Derived d2(boost::move(d));
152    d2 = boost::move(d);
153    //]
154    return 0;
155 }
156 
157 #include <boost/move/detail/config_end.hpp>
158