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;
25     A() {++count;}
26     A(const A&) {++count;}
27     ~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
47     Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
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 
65     Deleter() : state_(5) {}
66 
67 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
68     template <class U>
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>
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:
84     int state() const {return state_;}
85     void set_state(int i) {state_ = i;}
86 
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 
98     CDeleter() : state_(5) {}
99 
100     int state() const {return state_;}
101     void set_state(int s) {state_ = s;}
102 
103     void operator()(A* p) {delete p;}
104 };
105 
106 std::unique_ptr<A>
107 source1()
108 {
109     return std::unique_ptr<A>(new A);
110 }
111 
112 void sink1(std::unique_ptr<A> p)
113 {
114 }
115 
116 std::unique_ptr<A, Deleter<A> >
117 source2()
118 {
119     return std::unique_ptr<A, Deleter<A> >(new A);
120 }
121 
122 void sink2(std::unique_ptr<A, Deleter<A> > p)
123 {
124 }
125 
126 std::unique_ptr<A, CDeleter&>
127 source3()
128 {
129     static CDeleter d;
130     return std::unique_ptr<A, CDeleter&>(new A, d);
131 }
132 
133 void sink3(std::unique_ptr<A, CDeleter&> p)
134 {
135 }
136 
137 int main()
138 {
139     sink1(source1());
140     sink2(source2());
141     sink3(source3());
142     assert(A::count == 0);
143 }
144