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