xref: /llvm-project/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp (revision 6900df37d26764b828dbc5c2f98a57abbce1583e)
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