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;
X(int i)30 X(int i) : i_(i) {}
31 X(X&& x) = default;
32 X& operator=(X&&) = default;
~X()33 ~X() {++dtor_called;}
34
operator ==(const X & x,const X & y)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;
Y(int i)45 Y(int i) : i_(i) {}
46 Y(Y&&) = default;
~Y()47 ~Y() {++dtor_called;}
48
operator ==(const Y & x,const Y & y)49 friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
swap(Y & x,Y & y)50 friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
51 };
52
53 unsigned Y::dtor_called = 0;
54
55 class Z
56 {
57 int i_;
58 public:
Z(int i)59 Z(int i) : i_(i) {}
Z(Z &&)60 Z(Z&&) {TEST_THROW(7);}
61
operator ==(const Z & x,const Z & y)62 friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
swap(Z &,Z &)63 friend void swap(Z&, Z&) {TEST_THROW(6);}
64 };
65
66 class W
67 {
68 int i_;
69 public:
W(int i)70 constexpr W(int i) : i_(i) {}
71
operator ==(const W & x,const W & y)72 friend constexpr bool operator==(const W& x, const W& y) {return x.i_ == y.i_;}
swap(W & x,W & y)73 friend TEST_CONSTEXPR_CXX20 void swap(W& x, W& y) noexcept {std::swap(x.i_, y.i_);}
74 };
75
76 template<class T>
check_swap()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
main(int,char **)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(opt2)) == true, "");
142 assert(static_cast<bool>(opt1) == false);
143 assert(static_cast<bool>(opt2) == false);
144 opt1.swap(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(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(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(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(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(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(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(opt2)) == false, "");
197 assert(static_cast<bool>(opt1) == false);
198 assert(static_cast<bool>(opt2) == false);
199 opt1.swap(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(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(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(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(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(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(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(opt2)) == false, "");
252 assert(static_cast<bool>(opt1) == false);
253 assert(static_cast<bool>(opt2) == false);
254 opt1.swap(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(1);
262 optional<Z> opt2;
263 static_assert(noexcept(opt1.swap(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(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(2);
284 static_assert(noexcept(opt1.swap(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(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(1);
304 optional<Z> opt2;
305 opt2.emplace(2);
306 static_assert(noexcept(opt1.swap(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(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