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