1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <memory>
11 
12 // unique_ptr
13 
14 // Test unique_ptr move ctor
15 
16 #include <memory>
17 #include <cassert>
18 
19 // test move ctor.  Should only require a MoveConstructible deleter, or if
20 //    deleter is a reference, not even that.
21 
22 struct A
23 {
24     static int count;
AA25     A() {++count;}
AA26     A(const A&) {++count;}
~AA27     ~A() {--count;}
28 };
29 
30 int A::count = 0;
31 
32 template <class T>
33 class Deleter
34 {
35     int state_;
36 
37 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
38     Deleter(const Deleter&);
39     Deleter& operator=(const Deleter&);
40 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
41     Deleter(Deleter&);
42     Deleter& operator=(Deleter&);
43 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
44 
45 public:
46 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Deleter(Deleter && r)47     Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
operator =(Deleter && r)48     Deleter& operator=(Deleter&& r)
49     {
50         state_ = r.state_;
51         r.state_ = 0;
52         return *this;
53     }
54 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
55     operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
56     Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
57     Deleter& operator=(std::__rv<Deleter> r)
58     {
59         state_ = r->state_;
60         r->state_ = 0;
61         return *this;
62     }
63 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
64 
Deleter()65     Deleter() : state_(5) {}
66 
67 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
68     template <class U>
Deleter(Deleter<U> && d,typename std::enable_if<!std::is_same<U,T>::value>::type * =0)69         Deleter(Deleter<U>&& d,
70             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
71             : state_(d.state()) {d.set_state(0);}
72 
73 private:
74     template <class U>
75         Deleter(const Deleter<U>& d,
76             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
77 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
78     template <class U>
Deleter(Deleter<U> d,typename std::enable_if<!std::is_same<U,T>::value>::type * =0)79         Deleter(Deleter<U> d,
80             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
81             : state_(d.state()) {}
82 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
83 public:
state() const84     int state() const {return state_;}
set_state(int i)85     void set_state(int i) {state_ = i;}
86 
operator ()(T * p)87     void operator()(T* p) {delete p;}
88 };
89 
90 class CDeleter
91 {
92     int state_;
93 
94     CDeleter(CDeleter&);
95     CDeleter& operator=(CDeleter&);
96 public:
97 
CDeleter()98     CDeleter() : state_(5) {}
99 
state() const100     int state() const {return state_;}
set_state(int s)101     void set_state(int s) {state_ = s;}
102 
operator ()(A * p)103     void operator()(A* p) {delete p;}
104 };
105 
main()106 int main()
107 {
108     {
109     std::unique_ptr<A> s(new A);
110     A* p = s.get();
111     std::unique_ptr<A> s2 = std::move(s);
112     assert(s2.get() == p);
113     assert(s.get() == 0);
114     assert(A::count == 1);
115     }
116     assert(A::count == 0);
117     {
118     std::unique_ptr<A, Deleter<A> > s(new A);
119     A* p = s.get();
120     std::unique_ptr<A, Deleter<A> > s2 = std::move(s);
121     assert(s2.get() == p);
122     assert(s.get() == 0);
123     assert(A::count == 1);
124     assert(s2.get_deleter().state() == 5);
125     assert(s.get_deleter().state() == 0);
126     }
127     assert(A::count == 0);
128     {
129     CDeleter d;
130     std::unique_ptr<A, CDeleter&> s(new A, d);
131     A* p = s.get();
132     std::unique_ptr<A, CDeleter&> s2 = std::move(s);
133     assert(s2.get() == p);
134     assert(s.get() == 0);
135     assert(A::count == 1);
136     d.set_state(6);
137     assert(s2.get_deleter().state() == d.state());
138     assert(s.get_deleter().state() ==  d.state());
139     }
140     assert(A::count == 0);
141 }
142