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
main(int,char **)67 int main(int, char**)
68 {
69 {
70 optional<int> opt1;
71 optional<int> opt2;
72 static_assert(noexcept(opt1.swap(opt2)) == true, "");
73 assert(static_cast<bool>(opt1) == false);
74 assert(static_cast<bool>(opt2) == false);
75 opt1.swap(opt2);
76 assert(static_cast<bool>(opt1) == false);
77 assert(static_cast<bool>(opt2) == false);
78 }
79 {
80 optional<int> opt1(1);
81 optional<int> opt2;
82 static_assert(noexcept(opt1.swap(opt2)) == true, "");
83 assert(static_cast<bool>(opt1) == true);
84 assert(*opt1 == 1);
85 assert(static_cast<bool>(opt2) == false);
86 opt1.swap(opt2);
87 assert(static_cast<bool>(opt1) == false);
88 assert(static_cast<bool>(opt2) == true);
89 assert(*opt2 == 1);
90 }
91 {
92 optional<int> opt1;
93 optional<int> opt2(2);
94 static_assert(noexcept(opt1.swap(opt2)) == true, "");
95 assert(static_cast<bool>(opt1) == false);
96 assert(static_cast<bool>(opt2) == true);
97 assert(*opt2 == 2);
98 opt1.swap(opt2);
99 assert(static_cast<bool>(opt1) == true);
100 assert(*opt1 == 2);
101 assert(static_cast<bool>(opt2) == false);
102 }
103 {
104 optional<int> opt1(1);
105 optional<int> opt2(2);
106 static_assert(noexcept(opt1.swap(opt2)) == true, "");
107 assert(static_cast<bool>(opt1) == true);
108 assert(*opt1 == 1);
109 assert(static_cast<bool>(opt2) == true);
110 assert(*opt2 == 2);
111 opt1.swap(opt2);
112 assert(static_cast<bool>(opt1) == true);
113 assert(*opt1 == 2);
114 assert(static_cast<bool>(opt2) == true);
115 assert(*opt2 == 1);
116 }
117 {
118 optional<X> opt1;
119 optional<X> opt2;
120 static_assert(noexcept(opt1.swap(opt2)) == true, "");
121 assert(static_cast<bool>(opt1) == false);
122 assert(static_cast<bool>(opt2) == false);
123 opt1.swap(opt2);
124 assert(static_cast<bool>(opt1) == false);
125 assert(static_cast<bool>(opt2) == false);
126 assert(X::dtor_called == 0);
127 }
128 {
129 optional<X> opt1(1);
130 optional<X> opt2;
131 static_assert(noexcept(opt1.swap(opt2)) == true, "");
132 assert(static_cast<bool>(opt1) == true);
133 assert(*opt1 == 1);
134 assert(static_cast<bool>(opt2) == false);
135 X::dtor_called = 0;
136 opt1.swap(opt2);
137 assert(X::dtor_called == 1);
138 assert(static_cast<bool>(opt1) == false);
139 assert(static_cast<bool>(opt2) == true);
140 assert(*opt2 == 1);
141 }
142 {
143 optional<X> opt1;
144 optional<X> opt2(2);
145 static_assert(noexcept(opt1.swap(opt2)) == true, "");
146 assert(static_cast<bool>(opt1) == false);
147 assert(static_cast<bool>(opt2) == true);
148 assert(*opt2 == 2);
149 X::dtor_called = 0;
150 opt1.swap(opt2);
151 assert(X::dtor_called == 1);
152 assert(static_cast<bool>(opt1) == true);
153 assert(*opt1 == 2);
154 assert(static_cast<bool>(opt2) == false);
155 }
156 {
157 optional<X> opt1(1);
158 optional<X> opt2(2);
159 static_assert(noexcept(opt1.swap(opt2)) == true, "");
160 assert(static_cast<bool>(opt1) == true);
161 assert(*opt1 == 1);
162 assert(static_cast<bool>(opt2) == true);
163 assert(*opt2 == 2);
164 X::dtor_called = 0;
165 opt1.swap(opt2);
166 assert(X::dtor_called == 1); // from inside std::swap
167 assert(static_cast<bool>(opt1) == true);
168 assert(*opt1 == 2);
169 assert(static_cast<bool>(opt2) == true);
170 assert(*opt2 == 1);
171 }
172 {
173 optional<Y> opt1;
174 optional<Y> opt2;
175 static_assert(noexcept(opt1.swap(opt2)) == false, "");
176 assert(static_cast<bool>(opt1) == false);
177 assert(static_cast<bool>(opt2) == false);
178 opt1.swap(opt2);
179 assert(static_cast<bool>(opt1) == false);
180 assert(static_cast<bool>(opt2) == false);
181 assert(Y::dtor_called == 0);
182 }
183 {
184 optional<Y> opt1(1);
185 optional<Y> opt2;
186 static_assert(noexcept(opt1.swap(opt2)) == false, "");
187 assert(static_cast<bool>(opt1) == true);
188 assert(*opt1 == 1);
189 assert(static_cast<bool>(opt2) == false);
190 Y::dtor_called = 0;
191 opt1.swap(opt2);
192 assert(Y::dtor_called == 1);
193 assert(static_cast<bool>(opt1) == false);
194 assert(static_cast<bool>(opt2) == true);
195 assert(*opt2 == 1);
196 }
197 {
198 optional<Y> opt1;
199 optional<Y> opt2(2);
200 static_assert(noexcept(opt1.swap(opt2)) == false, "");
201 assert(static_cast<bool>(opt1) == false);
202 assert(static_cast<bool>(opt2) == true);
203 assert(*opt2 == 2);
204 Y::dtor_called = 0;
205 opt1.swap(opt2);
206 assert(Y::dtor_called == 1);
207 assert(static_cast<bool>(opt1) == true);
208 assert(*opt1 == 2);
209 assert(static_cast<bool>(opt2) == false);
210 }
211 {
212 optional<Y> opt1(1);
213 optional<Y> opt2(2);
214 static_assert(noexcept(opt1.swap(opt2)) == false, "");
215 assert(static_cast<bool>(opt1) == true);
216 assert(*opt1 == 1);
217 assert(static_cast<bool>(opt2) == true);
218 assert(*opt2 == 2);
219 Y::dtor_called = 0;
220 opt1.swap(opt2);
221 assert(Y::dtor_called == 0);
222 assert(static_cast<bool>(opt1) == true);
223 assert(*opt1 == 2);
224 assert(static_cast<bool>(opt2) == true);
225 assert(*opt2 == 1);
226 }
227 {
228 optional<Z> opt1;
229 optional<Z> opt2;
230 static_assert(noexcept(opt1.swap(opt2)) == false, "");
231 assert(static_cast<bool>(opt1) == false);
232 assert(static_cast<bool>(opt2) == false);
233 opt1.swap(opt2);
234 assert(static_cast<bool>(opt1) == false);
235 assert(static_cast<bool>(opt2) == false);
236 }
237 #ifndef TEST_HAS_NO_EXCEPTIONS
238 {
239 optional<Z> opt1;
240 opt1.emplace(1);
241 optional<Z> opt2;
242 static_assert(noexcept(opt1.swap(opt2)) == false, "");
243 assert(static_cast<bool>(opt1) == true);
244 assert(*opt1 == 1);
245 assert(static_cast<bool>(opt2) == false);
246 try
247 {
248 opt1.swap(opt2);
249 assert(false);
250 }
251 catch (int i)
252 {
253 assert(i == 7);
254 }
255 assert(static_cast<bool>(opt1) == true);
256 assert(*opt1 == 1);
257 assert(static_cast<bool>(opt2) == false);
258 }
259 {
260 optional<Z> opt1;
261 optional<Z> opt2;
262 opt2.emplace(2);
263 static_assert(noexcept(opt1.swap(opt2)) == false, "");
264 assert(static_cast<bool>(opt1) == false);
265 assert(static_cast<bool>(opt2) == true);
266 assert(*opt2 == 2);
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) == false);
277 assert(static_cast<bool>(opt2) == true);
278 assert(*opt2 == 2);
279 }
280 {
281 optional<Z> opt1;
282 opt1.emplace(1);
283 optional<Z> opt2;
284 opt2.emplace(2);
285 static_assert(noexcept(opt1.swap(opt2)) == false, "");
286 assert(static_cast<bool>(opt1) == true);
287 assert(*opt1 == 1);
288 assert(static_cast<bool>(opt2) == true);
289 assert(*opt2 == 2);
290 try
291 {
292 opt1.swap(opt2);
293 assert(false);
294 }
295 catch (int i)
296 {
297 assert(i == 6);
298 }
299 assert(static_cast<bool>(opt1) == true);
300 assert(*opt1 == 1);
301 assert(static_cast<bool>(opt2) == true);
302 assert(*opt2 == 2);
303 }
304 #endif
305
306 return 0;
307 }
308