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

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