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