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 TEST_CONSTEXPR_CXX23 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 TEST_CONSTEXPR_CXX23 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 TEST_CONSTEXPR_CXX23 void checkCtor(LHS& lhs, RHS& rhs, A* RHSVal) {
51 assert(lhs.get() == RHSVal);
52 assert(rhs.get() == nullptr);
53 if (!TEST_IS_CONSTANT_EVALUATED) {
54 assert(A::count == 1);
55 assert(B::count == 1);
56 }
57 }
58
checkNoneAlive()59 TEST_CONSTEXPR_CXX23 void checkNoneAlive() {
60 if (!TEST_IS_CONSTANT_EVALUATED) {
61 assert(A::count == 0);
62 assert(B::count == 0);
63 }
64 }
65
66 template <class T>
67 struct NCConvertingDeleter {
68 TEST_CONSTEXPR_CXX23 NCConvertingDeleter() = default;
69 NCConvertingDeleter(NCConvertingDeleter const&) = delete;
70 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter&&) = default;
71
72 template <class U>
NCConvertingDeleterNCConvertingDeleter73 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
74
operator ()NCConvertingDeleter75 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}
76 };
77
78 template <class T>
79 struct NCConvertingDeleter<T[]> {
80 TEST_CONSTEXPR_CXX23 NCConvertingDeleter() = default;
81 NCConvertingDeleter(NCConvertingDeleter const&) = delete;
82 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter&&) = default;
83
84 template <class U>
NCConvertingDeleterNCConvertingDeleter85 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
86
operator ()NCConvertingDeleter87 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}
88 };
89
90 struct NCGenericDeleter {
91 TEST_CONSTEXPR_CXX23 NCGenericDeleter() = default;
92 NCGenericDeleter(NCGenericDeleter const&) = delete;
93 TEST_CONSTEXPR_CXX23 NCGenericDeleter(NCGenericDeleter&&) = default;
94
operator ()NCGenericDeleter95 TEST_CONSTEXPR_CXX23 void operator()(void*) const {}
96 };
97
test_sfinae()98 TEST_CONSTEXPR_CXX23 void test_sfinae() {
99 using DA = NCConvertingDeleter<A>; // non-copyable deleters
100 using DB = NCConvertingDeleter<B>;
101 using UA = std::unique_ptr<A>;
102 using UB = std::unique_ptr<B>;
103 using UAD = std::unique_ptr<A, DA>;
104 using UBD = std::unique_ptr<B, DB>;
105 { // cannot move from an lvalue
106 static_assert(std::is_constructible<UA, UB&&>::value, "");
107 static_assert(!std::is_constructible<UA, UB&>::value, "");
108 static_assert(!std::is_constructible<UA, const UB&>::value, "");
109 }
110 { // cannot move if the deleter-types cannot convert
111 static_assert(std::is_constructible<UAD, UBD&&>::value, "");
112 static_assert(!std::is_constructible<UAD, UB&&>::value, "");
113 static_assert(!std::is_constructible<UA, UBD&&>::value, "");
114 }
115 { // cannot move-convert with reference deleters of different types
116 using UA1 = std::unique_ptr<A, DA&>;
117 using UB1 = std::unique_ptr<B, DB&>;
118 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
119 }
120 { // cannot move-convert with reference deleters of different types
121 using UA1 = std::unique_ptr<A, const DA&>;
122 using UB1 = std::unique_ptr<B, const DB&>;
123 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
124 }
125 { // cannot move-convert from unique_ptr<Array[]>
126 using UA1 = std::unique_ptr<A>;
127 using UA2 = std::unique_ptr<A[]>;
128 using UB1 = std::unique_ptr<B[]>;
129 static_assert(!std::is_constructible<UA1, UA2&&>::value, "");
130 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
131 }
132 { // cannot move-convert from unique_ptr<Array[]>
133 using UA1 = std::unique_ptr<A, NCGenericDeleter>;
134 using UA2 = std::unique_ptr<A[], NCGenericDeleter>;
135 using UB1 = std::unique_ptr<B[], NCGenericDeleter>;
136 static_assert(!std::is_constructible<UA1, UA2&&>::value, "");
137 static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
138 }
139 }
140
test_noexcept()141 TEST_CONSTEXPR_CXX23 void test_noexcept() {
142 {
143 typedef std::unique_ptr<A> APtr;
144 typedef std::unique_ptr<B> BPtr;
145 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
146 }
147 {
148 typedef std::unique_ptr<A, Deleter<A> > APtr;
149 typedef std::unique_ptr<B, Deleter<B> > BPtr;
150 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
151 }
152 {
153 typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
154 typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
155 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
156 }
157 {
158 typedef std::unique_ptr<A, const NCConstDeleter<A>&> APtr;
159 typedef std::unique_ptr<B, const NCConstDeleter<A>&> BPtr;
160 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
161 }
162 }
163
test()164 TEST_CONSTEXPR_CXX23 bool test() {
165 {
166 test_sfinae();
167 test_noexcept();
168 }
169 {
170 typedef std::unique_ptr<A> APtr;
171 typedef std::unique_ptr<B> BPtr;
172 { // explicit
173 BPtr b(new B);
174 A* p = b.get();
175 APtr a(std::move(b));
176 checkCtor(a, b, p);
177 }
178 checkNoneAlive();
179 { // implicit
180 BPtr b(new B);
181 A* p = b.get();
182 APtr a = std::move(b);
183 checkCtor(a, b, p);
184 }
185 checkNoneAlive();
186 }
187 { // test with moveable deleters
188 typedef std::unique_ptr<A, Deleter<A> > APtr;
189 typedef std::unique_ptr<B, Deleter<B> > BPtr;
190 {
191 Deleter<B> del(5);
192 BPtr b(new B, std::move(del));
193 A* p = b.get();
194 APtr a(std::move(b));
195 checkCtor(a, b, p);
196 checkDeleter(a, b, 5, 0);
197 }
198 checkNoneAlive();
199 {
200 Deleter<B> del(5);
201 BPtr b(new B, std::move(del));
202 A* p = b.get();
203 APtr a = std::move(b);
204 checkCtor(a, b, p);
205 checkDeleter(a, b, 5, 0);
206 }
207 checkNoneAlive();
208 }
209 { // test with reference deleters
210 typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
211 typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
212 NCDeleter<A> del(5);
213 {
214 BPtr b(new B, del);
215 A* p = b.get();
216 APtr a(std::move(b));
217 checkCtor(a, b, p);
218 checkReferenceDeleter(a, b);
219 }
220 checkNoneAlive();
221 {
222 BPtr b(new B, del);
223 A* p = b.get();
224 APtr a = std::move(b);
225 checkCtor(a, b, p);
226 checkReferenceDeleter(a, b);
227 }
228 checkNoneAlive();
229 }
230 {
231 typedef std::unique_ptr<A, CDeleter<A> > APtr;
232 typedef std::unique_ptr<B, CDeleter<B>&> BPtr;
233 CDeleter<B> del(5);
234 {
235 BPtr b(new B, del);
236 A* p = b.get();
237 APtr a(std::move(b));
238 checkCtor(a, b, p);
239 checkDeleter(a, b, 5, 5);
240 }
241 checkNoneAlive();
242 {
243 BPtr b(new B, del);
244 A* p = b.get();
245 APtr a = std::move(b);
246 checkCtor(a, b, p);
247 checkDeleter(a, b, 5, 5);
248 }
249 checkNoneAlive();
250 }
251
252 return true;
253 }
254
main(int,char **)255 int main(int, char**) {
256 test();
257 #if TEST_STD_VER >= 23
258 static_assert(test());
259 #endif
260
261 return 0;
262 }
263