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++98, 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
22 using std::optional;
23
24 class X
25 {
26 int i_;
27 public:
28 static unsigned dtor_called;
X(int i)29 X(int i) : i_(i) {}
30 X(X&& x) = default;
31 X& operator=(X&&) = default;
~X()32 ~X() {++dtor_called;}
33
operator ==(const X & x,const X & y)34 friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
35 };
36
37 unsigned X::dtor_called = 0;
38
39 class Y
40 {
41 int i_;
42 public:
43 static unsigned dtor_called;
Y(int i)44 Y(int i) : i_(i) {}
45 Y(Y&&) = default;
~Y()46 ~Y() {++dtor_called;}
47
operator ==(const Y & x,const Y & y)48 friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
swap(Y & x,Y & y)49 friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
50 };
51
52 unsigned Y::dtor_called = 0;
53
54 class Z
55 {
56 int i_;
57 public:
Z(int i)58 Z(int i) : i_(i) {}
Z(Z &&)59 Z(Z&&) { TEST_THROW(7);}
60
operator ==(const Z & x,const Z & y)61 friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
swap(Z &,Z &)62 friend void swap(Z&, Z&) { TEST_THROW(6);}
63 };
64
65
66 struct NonSwappable {
67 NonSwappable(NonSwappable const&) = delete;
68 };
69 void swap(NonSwappable&, NonSwappable&) = delete;
70
test_swap_sfinae()71 void 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
main(int,char **)112 int 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