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
11 // <memory>
12
13 // unique_ptr
14
15 // Test unique_ptr converting move ctor
16
17 // NOTE: unique_ptr does not provide converting constructors in C++03
18 // UNSUPPORTED: c++98, c++03
19
20 #include <memory>
21 #include <type_traits>
22 #include <utility>
23 #include <cassert>
24
25 #include "test_macros.h"
26 #include "unique_ptr_test_helper.h"
27
28 // test converting move ctor. Should only require a MoveConstructible deleter, or if
29 // deleter is a reference, not even that.
30 // Explicit version
31
32 template <class LHS, class RHS>
checkReferenceDeleter(LHS & lhs,RHS & rhs)33 void checkReferenceDeleter(LHS& lhs, RHS& rhs) {
34 typedef typename LHS::deleter_type NewDel;
35 static_assert(std::is_reference<NewDel>::value, "");
36 rhs.get_deleter().set_state(42);
37 assert(rhs.get_deleter().state() == 42);
38 assert(lhs.get_deleter().state() == 42);
39 lhs.get_deleter().set_state(99);
40 assert(lhs.get_deleter().state() == 99);
41 assert(rhs.get_deleter().state() == 99);
42 }
43
44 template <class LHS, class RHS>
checkDeleter(LHS & lhs,RHS & rhs,int LHSVal,int RHSVal)45 void checkDeleter(LHS& lhs, RHS& rhs, int LHSVal, int RHSVal) {
46 assert(lhs.get_deleter().state() == LHSVal);
47 assert(rhs.get_deleter().state() == RHSVal);
48 }
49
50 template <class LHS, class RHS>
checkCtor(LHS & lhs,RHS & rhs,A * RHSVal)51 void checkCtor(LHS& lhs, RHS& rhs, A* RHSVal) {
52 assert(lhs.get() == RHSVal);
53 assert(rhs.get() == nullptr);
54 assert(A::count == 1);
55 assert(B::count == 1);
56 }
57
checkNoneAlive()58 void checkNoneAlive() {
59 assert(A::count == 0);
60 assert(B::count == 0);
61 }
62
63 template <class T>
64 struct NCConvertingDeleter {
65 NCConvertingDeleter() = default;
66 NCConvertingDeleter(NCConvertingDeleter const&) = delete;
67 NCConvertingDeleter(NCConvertingDeleter&&) = default;
68
69 template <class U>
NCConvertingDeleterNCConvertingDeleter70 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
71
operator ()NCConvertingDeleter72 void operator()(T*) const {}
73 };
74
75 template <class T>
76 struct NCConvertingDeleter<T[]> {
77 NCConvertingDeleter() = default;
78 NCConvertingDeleter(NCConvertingDeleter const&) = delete;
79 NCConvertingDeleter(NCConvertingDeleter&&) = default;
80
81 template <class U>
NCConvertingDeleterNCConvertingDeleter82 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
83
operator ()NCConvertingDeleter84 void operator()(T*) const {}
85 };
86
87 struct NCGenericDeleter {
88 NCGenericDeleter() = default;
89 NCGenericDeleter(NCGenericDeleter const&) = delete;
90 NCGenericDeleter(NCGenericDeleter&&) = default;
91
operator ()NCGenericDeleter92 void operator()(void*) const {}
93 };
94
test_sfinae()95 void test_sfinae() {
96 using DA = NCConvertingDeleter<A>; // non-copyable deleters
97 using DB = NCConvertingDeleter<B>;
98 using UA = std::unique_ptr<A>;
99 using UB = std::unique_ptr<B>;
100 using UAD = std::unique_ptr<A, DA>;
101 using UBD = std::unique_ptr<B, DB>;
102 { // cannot move from an lvalue
103 static_assert(std::is_constructible<UA, UB&&>::value, "");
104 static_assert(!std::is_constructible<UA, UB&>::value, "");
105 static_assert(!std::is_constructible<UA, const UB&>::value, "");
106 }
107 { // cannot move if the deleter-types cannot convert
108 static_assert(std::is_constructible<UAD, UBD&&>::value, "");
109 static_assert(!std::is_constructible<UAD, UB&&>::value, "");
110 static_assert(!std::is_constructible<UA, UBD&&>::value, "");
111 }
112 { // cannot move-convert with reference deleters of different types
113 using UA1 = std::unique_ptr<A, DA&>;
114 using UB1 = std::unique_ptr<B, DB&>;
115 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
116 }
117 { // cannot move-convert with reference deleters of different types
118 using UA1 = std::unique_ptr<A, const DA&>;
119 using UB1 = std::unique_ptr<B, const DB&>;
120 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
121 }
122 { // cannot move-convert from unique_ptr<Array[]>
123 using UA1 = std::unique_ptr<A>;
124 using UA2 = std::unique_ptr<A[]>;
125 using UB1 = std::unique_ptr<B[]>;
126 static_assert(!std::is_constructible<UA1, UA2&&>::value, "");
127 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
128 }
129 { // cannot move-convert from unique_ptr<Array[]>
130 using UA1 = std::unique_ptr<A, NCGenericDeleter>;
131 using UA2 = std::unique_ptr<A[], NCGenericDeleter>;
132 using UB1 = std::unique_ptr<B[], NCGenericDeleter>;
133 static_assert(!std::is_constructible<UA1, UA2&&>::value, "");
134 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
135 }
136 }
137
test_noexcept()138 void test_noexcept() {
139 {
140 typedef std::unique_ptr<A> APtr;
141 typedef std::unique_ptr<B> BPtr;
142 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
143 }
144 {
145 typedef std::unique_ptr<A, Deleter<A> > APtr;
146 typedef std::unique_ptr<B, Deleter<B> > BPtr;
147 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
148 }
149 {
150 typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
151 typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
152 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
153 }
154 {
155 typedef std::unique_ptr<A, const NCConstDeleter<A>&> APtr;
156 typedef std::unique_ptr<B, const NCConstDeleter<A>&> BPtr;
157 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
158 }
159 }
160
main()161 int main() {
162 {
163 test_sfinae();
164 test_noexcept();
165 }
166 {
167 typedef std::unique_ptr<A> APtr;
168 typedef std::unique_ptr<B> BPtr;
169 { // explicit
170 BPtr b(new B);
171 A* p = b.get();
172 APtr a(std::move(b));
173 checkCtor(a, b, p);
174 }
175 checkNoneAlive();
176 { // implicit
177 BPtr b(new B);
178 A* p = b.get();
179 APtr a = std::move(b);
180 checkCtor(a, b, p);
181 }
182 checkNoneAlive();
183 }
184 { // test with moveable deleters
185 typedef std::unique_ptr<A, Deleter<A> > APtr;
186 typedef std::unique_ptr<B, Deleter<B> > BPtr;
187 {
188 Deleter<B> del(5);
189 BPtr b(new B, std::move(del));
190 A* p = b.get();
191 APtr a(std::move(b));
192 checkCtor(a, b, p);
193 checkDeleter(a, b, 5, 0);
194 }
195 checkNoneAlive();
196 {
197 Deleter<B> del(5);
198 BPtr b(new B, std::move(del));
199 A* p = b.get();
200 APtr a = std::move(b);
201 checkCtor(a, b, p);
202 checkDeleter(a, b, 5, 0);
203 }
204 checkNoneAlive();
205 }
206 { // test with reference deleters
207 typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
208 typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
209 NCDeleter<A> del(5);
210 {
211 BPtr b(new B, del);
212 A* p = b.get();
213 APtr a(std::move(b));
214 checkCtor(a, b, p);
215 checkReferenceDeleter(a, b);
216 }
217 checkNoneAlive();
218 {
219 BPtr b(new B, del);
220 A* p = b.get();
221 APtr a = std::move(b);
222 checkCtor(a, b, p);
223 checkReferenceDeleter(a, b);
224 }
225 checkNoneAlive();
226 }
227 {
228 typedef std::unique_ptr<A, CDeleter<A> > APtr;
229 typedef std::unique_ptr<B, CDeleter<B>&> BPtr;
230 CDeleter<B> del(5);
231 {
232 BPtr b(new B, del);
233 A* p = b.get();
234 APtr a(std::move(b));
235 checkCtor(a, b, p);
236 checkDeleter(a, b, 5, 5);
237 }
238 checkNoneAlive();
239 {
240 BPtr b(new B, del);
241 A* p = b.get();
242 APtr a = std::move(b);
243 checkCtor(a, b, p);
244 checkDeleter(a, b, 5, 5);
245 }
246 checkNoneAlive();
247 }
248 }
249