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