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 | // UNSUPPORTED: c++03, c++11, c++14 |
10 | // <optional> |
11 | |
12 | // void swap(optional&) |
13 | // noexcept(is_nothrow_move_constructible<T>::value && |
14 | // is_nothrow_swappable<T>::value) |
15 | |
16 | #include <optional> |
17 | #include <type_traits> |
18 | #include <cassert> |
19 | |
20 | #include "test_macros.h" |
21 | #include "archetypes.h" |
22 | |
23 | using std::optional; |
24 | |
25 | class X |
26 | { |
27 | int i_; |
28 | public: |
29 | static unsigned dtor_called; |
30 | X(int i) : i_(i) {} |
31 | X(X&& x) = default; |
32 | X& operator=(X&&) = default; |
33 | ~X() {++dtor_called;} |
34 | |
35 | friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} |
36 | }; |
37 | |
38 | unsigned X::dtor_called = 0; |
39 | |
40 | class Y |
41 | { |
42 | int i_; |
43 | public: |
44 | static unsigned dtor_called; |
45 | Y(int i) : i_(i) {} |
46 | Y(Y&&) = default; |
47 | ~Y() {++dtor_called;} |
48 | |
49 | friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} |
50 | friend void swap(Y& x, Y& y) {std::swap(a&: x.i_, b&: y.i_);} |
51 | }; |
52 | |
53 | unsigned Y::dtor_called = 0; |
54 | |
55 | class Z |
56 | { |
57 | int i_; |
58 | public: |
59 | Z(int i) : i_(i) {} |
60 | Z(Z&&) {TEST_THROW(7);} |
61 | |
62 | friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} |
63 | friend void swap(Z&, Z&) {TEST_THROW(6);} |
64 | }; |
65 | |
66 | class W |
67 | { |
68 | int i_; |
69 | public: |
70 | constexpr W(int i) : i_(i) {} |
71 | |
72 | friend constexpr bool operator==(const W& x, const W& y) {return x.i_ == y.i_;} |
73 | friend TEST_CONSTEXPR_CXX20 void swap(W& x, W& y) noexcept {std::swap(a&: x.i_, b&: y.i_);} |
74 | }; |
75 | |
76 | template<class T> |
77 | TEST_CONSTEXPR_CXX20 bool check_swap() |
78 | { |
79 | { |
80 | optional<T> opt1; |
81 | optional<T> opt2; |
82 | static_assert(noexcept(opt1.swap(opt2)) == true); |
83 | assert(static_cast<bool>(opt1) == false); |
84 | assert(static_cast<bool>(opt2) == false); |
85 | opt1.swap(opt2); |
86 | assert(static_cast<bool>(opt1) == false); |
87 | assert(static_cast<bool>(opt2) == false); |
88 | } |
89 | { |
90 | optional<T> opt1(1); |
91 | optional<T> opt2; |
92 | static_assert(noexcept(opt1.swap(opt2)) == true); |
93 | assert(static_cast<bool>(opt1) == true); |
94 | assert(*opt1 == 1); |
95 | assert(static_cast<bool>(opt2) == false); |
96 | opt1.swap(opt2); |
97 | assert(static_cast<bool>(opt1) == false); |
98 | assert(static_cast<bool>(opt2) == true); |
99 | assert(*opt2 == 1); |
100 | } |
101 | { |
102 | optional<T> opt1; |
103 | optional<T> opt2(2); |
104 | static_assert(noexcept(opt1.swap(opt2)) == true, "" ); |
105 | assert(static_cast<bool>(opt1) == false); |
106 | assert(static_cast<bool>(opt2) == true); |
107 | assert(*opt2 == 2); |
108 | opt1.swap(opt2); |
109 | assert(static_cast<bool>(opt1) == true); |
110 | assert(*opt1 == 2); |
111 | assert(static_cast<bool>(opt2) == false); |
112 | } |
113 | { |
114 | optional<T> opt1(1); |
115 | optional<T> opt2(2); |
116 | static_assert(noexcept(opt1.swap(opt2)) == true, "" ); |
117 | assert(static_cast<bool>(opt1) == true); |
118 | assert(*opt1 == 1); |
119 | assert(static_cast<bool>(opt2) == true); |
120 | assert(*opt2 == 2); |
121 | opt1.swap(opt2); |
122 | assert(static_cast<bool>(opt1) == true); |
123 | assert(*opt1 == 2); |
124 | assert(static_cast<bool>(opt2) == true); |
125 | assert(*opt2 == 1); |
126 | } |
127 | return true; |
128 | } |
129 | |
130 | int main(int, char**) |
131 | { |
132 | check_swap<int>(); |
133 | check_swap<W>(); |
134 | #if TEST_STD_VER > 17 |
135 | static_assert(check_swap<int>()); |
136 | static_assert(check_swap<W>()); |
137 | #endif |
138 | { |
139 | optional<X> opt1; |
140 | optional<X> opt2; |
141 | static_assert(noexcept(opt1.swap(other&: opt2)) == true, "" ); |
142 | assert(static_cast<bool>(opt1) == false); |
143 | assert(static_cast<bool>(opt2) == false); |
144 | opt1.swap(other&: opt2); |
145 | assert(static_cast<bool>(opt1) == false); |
146 | assert(static_cast<bool>(opt2) == false); |
147 | assert(X::dtor_called == 0); |
148 | } |
149 | { |
150 | optional<X> opt1(1); |
151 | optional<X> opt2; |
152 | static_assert(noexcept(opt1.swap(other&: opt2)) == true, "" ); |
153 | assert(static_cast<bool>(opt1) == true); |
154 | assert(*opt1 == 1); |
155 | assert(static_cast<bool>(opt2) == false); |
156 | X::dtor_called = 0; |
157 | opt1.swap(other&: opt2); |
158 | assert(X::dtor_called == 1); |
159 | assert(static_cast<bool>(opt1) == false); |
160 | assert(static_cast<bool>(opt2) == true); |
161 | assert(*opt2 == 1); |
162 | } |
163 | { |
164 | optional<X> opt1; |
165 | optional<X> opt2(2); |
166 | static_assert(noexcept(opt1.swap(other&: opt2)) == true, "" ); |
167 | assert(static_cast<bool>(opt1) == false); |
168 | assert(static_cast<bool>(opt2) == true); |
169 | assert(*opt2 == 2); |
170 | X::dtor_called = 0; |
171 | opt1.swap(other&: opt2); |
172 | assert(X::dtor_called == 1); |
173 | assert(static_cast<bool>(opt1) == true); |
174 | assert(*opt1 == 2); |
175 | assert(static_cast<bool>(opt2) == false); |
176 | } |
177 | { |
178 | optional<X> opt1(1); |
179 | optional<X> opt2(2); |
180 | static_assert(noexcept(opt1.swap(other&: opt2)) == true, "" ); |
181 | assert(static_cast<bool>(opt1) == true); |
182 | assert(*opt1 == 1); |
183 | assert(static_cast<bool>(opt2) == true); |
184 | assert(*opt2 == 2); |
185 | X::dtor_called = 0; |
186 | opt1.swap(other&: opt2); |
187 | assert(X::dtor_called == 1); // from inside std::swap |
188 | assert(static_cast<bool>(opt1) == true); |
189 | assert(*opt1 == 2); |
190 | assert(static_cast<bool>(opt2) == true); |
191 | assert(*opt2 == 1); |
192 | } |
193 | { |
194 | optional<Y> opt1; |
195 | optional<Y> opt2; |
196 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
197 | assert(static_cast<bool>(opt1) == false); |
198 | assert(static_cast<bool>(opt2) == false); |
199 | opt1.swap(other&: opt2); |
200 | assert(static_cast<bool>(opt1) == false); |
201 | assert(static_cast<bool>(opt2) == false); |
202 | assert(Y::dtor_called == 0); |
203 | } |
204 | { |
205 | optional<Y> opt1(1); |
206 | optional<Y> opt2; |
207 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
208 | assert(static_cast<bool>(opt1) == true); |
209 | assert(*opt1 == 1); |
210 | assert(static_cast<bool>(opt2) == false); |
211 | Y::dtor_called = 0; |
212 | opt1.swap(other&: opt2); |
213 | assert(Y::dtor_called == 1); |
214 | assert(static_cast<bool>(opt1) == false); |
215 | assert(static_cast<bool>(opt2) == true); |
216 | assert(*opt2 == 1); |
217 | } |
218 | { |
219 | optional<Y> opt1; |
220 | optional<Y> opt2(2); |
221 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
222 | assert(static_cast<bool>(opt1) == false); |
223 | assert(static_cast<bool>(opt2) == true); |
224 | assert(*opt2 == 2); |
225 | Y::dtor_called = 0; |
226 | opt1.swap(other&: opt2); |
227 | assert(Y::dtor_called == 1); |
228 | assert(static_cast<bool>(opt1) == true); |
229 | assert(*opt1 == 2); |
230 | assert(static_cast<bool>(opt2) == false); |
231 | } |
232 | { |
233 | optional<Y> opt1(1); |
234 | optional<Y> opt2(2); |
235 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
236 | assert(static_cast<bool>(opt1) == true); |
237 | assert(*opt1 == 1); |
238 | assert(static_cast<bool>(opt2) == true); |
239 | assert(*opt2 == 2); |
240 | Y::dtor_called = 0; |
241 | opt1.swap(other&: opt2); |
242 | assert(Y::dtor_called == 0); |
243 | assert(static_cast<bool>(opt1) == true); |
244 | assert(*opt1 == 2); |
245 | assert(static_cast<bool>(opt2) == true); |
246 | assert(*opt2 == 1); |
247 | } |
248 | { |
249 | optional<Z> opt1; |
250 | optional<Z> opt2; |
251 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
252 | assert(static_cast<bool>(opt1) == false); |
253 | assert(static_cast<bool>(opt2) == false); |
254 | opt1.swap(other&: opt2); |
255 | assert(static_cast<bool>(opt1) == false); |
256 | assert(static_cast<bool>(opt2) == false); |
257 | } |
258 | #ifndef TEST_HAS_NO_EXCEPTIONS |
259 | { |
260 | optional<Z> opt1; |
261 | opt1.emplace(args: 1); |
262 | optional<Z> opt2; |
263 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
264 | assert(static_cast<bool>(opt1) == true); |
265 | assert(*opt1 == 1); |
266 | assert(static_cast<bool>(opt2) == false); |
267 | try |
268 | { |
269 | opt1.swap(other&: opt2); |
270 | assert(false); |
271 | } |
272 | catch (int i) |
273 | { |
274 | assert(i == 7); |
275 | } |
276 | assert(static_cast<bool>(opt1) == true); |
277 | assert(*opt1 == 1); |
278 | assert(static_cast<bool>(opt2) == false); |
279 | } |
280 | { |
281 | optional<Z> opt1; |
282 | optional<Z> opt2; |
283 | opt2.emplace(args: 2); |
284 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
285 | assert(static_cast<bool>(opt1) == false); |
286 | assert(static_cast<bool>(opt2) == true); |
287 | assert(*opt2 == 2); |
288 | try |
289 | { |
290 | opt1.swap(other&: opt2); |
291 | assert(false); |
292 | } |
293 | catch (int i) |
294 | { |
295 | assert(i == 7); |
296 | } |
297 | assert(static_cast<bool>(opt1) == false); |
298 | assert(static_cast<bool>(opt2) == true); |
299 | assert(*opt2 == 2); |
300 | } |
301 | { |
302 | optional<Z> opt1; |
303 | opt1.emplace(args: 1); |
304 | optional<Z> opt2; |
305 | opt2.emplace(args: 2); |
306 | static_assert(noexcept(opt1.swap(other&: opt2)) == false, "" ); |
307 | assert(static_cast<bool>(opt1) == true); |
308 | assert(*opt1 == 1); |
309 | assert(static_cast<bool>(opt2) == true); |
310 | assert(*opt2 == 2); |
311 | try |
312 | { |
313 | opt1.swap(other&: opt2); |
314 | assert(false); |
315 | } |
316 | catch (int i) |
317 | { |
318 | assert(i == 6); |
319 | } |
320 | assert(static_cast<bool>(opt1) == true); |
321 | assert(*opt1 == 1); |
322 | assert(static_cast<bool>(opt2) == true); |
323 | assert(*opt2 == 2); |
324 | } |
325 | #endif |
326 | |
327 | return 0; |
328 | } |
329 | |