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