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