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
23using std::optional;
24
25class X
26{
27 int i_;
28public:
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
38unsigned X::dtor_called = 0;
39
40class Y
41{
42 int i_;
43public:
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
53unsigned Y::dtor_called = 0;
54
55class Z
56{
57 int i_;
58public:
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
66class W
67{
68 int i_;
69public:
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
76template<class T>
77TEST_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
130int 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

source code of libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp