1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <optional>
11 
12 // void swap(optional&)
13 //     noexcept(is_nothrow_move_constructible<T>::value &&
14 //              noexcept(swap(declval<T&>(), declval<T&>())));
15 
16 #include <experimental/optional>
17 #include <type_traits>
18 #include <cassert>
19 
20 #if _LIBCPP_STD_VER > 11
21 
22 using std::experimental::optional;
23 
24 class X
25 {
26     int i_;
27 public:
28     static unsigned dtor_called;
29     X(int i) : i_(i) {}
30     X(X&& x) = default;
31     X& operator=(X&&) = default;
32     ~X() {++dtor_called;}
33 
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;
44     Y(int i) : i_(i) {}
45     Y(Y&&) = default;
46     ~Y() {++dtor_called;}
47 
48     friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
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:
58     Z(int i) : i_(i) {}
59     Z(Z&&) {throw 7;}
60 
61     friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
62     friend void swap(Z& x, Z& y) {throw 6;}
63 };
64 
65 
66 #endif  // _LIBCPP_STD_VER > 11
67 
68 int main()
69 {
70 #if _LIBCPP_STD_VER > 11
71     {
72         optional<int> opt1;
73         optional<int> opt2;
74         static_assert(noexcept(opt1.swap(opt2)) == true, "");
75         assert(static_cast<bool>(opt1) == false);
76         assert(static_cast<bool>(opt2) == false);
77         opt1.swap(opt2);
78         assert(static_cast<bool>(opt1) == false);
79         assert(static_cast<bool>(opt2) == false);
80     }
81     {
82         optional<int> opt1(1);
83         optional<int> opt2;
84         static_assert(noexcept(opt1.swap(opt2)) == true, "");
85         assert(static_cast<bool>(opt1) == true);
86         assert(*opt1 == 1);
87         assert(static_cast<bool>(opt2) == false);
88         opt1.swap(opt2);
89         assert(static_cast<bool>(opt1) == false);
90         assert(static_cast<bool>(opt2) == true);
91         assert(*opt2 == 1);
92     }
93     {
94         optional<int> opt1;
95         optional<int> opt2(2);
96         static_assert(noexcept(opt1.swap(opt2)) == true, "");
97         assert(static_cast<bool>(opt1) == false);
98         assert(static_cast<bool>(opt2) == true);
99         assert(*opt2 == 2);
100         opt1.swap(opt2);
101         assert(static_cast<bool>(opt1) == true);
102         assert(*opt1 == 2);
103         assert(static_cast<bool>(opt2) == false);
104     }
105     {
106         optional<int> opt1(1);
107         optional<int> opt2(2);
108         static_assert(noexcept(opt1.swap(opt2)) == true, "");
109         assert(static_cast<bool>(opt1) == true);
110         assert(*opt1 == 1);
111         assert(static_cast<bool>(opt2) == true);
112         assert(*opt2 == 2);
113         opt1.swap(opt2);
114         assert(static_cast<bool>(opt1) == true);
115         assert(*opt1 == 2);
116         assert(static_cast<bool>(opt2) == true);
117         assert(*opt2 == 1);
118     }
119     {
120         optional<X> opt1;
121         optional<X> opt2;
122         static_assert(noexcept(opt1.swap(opt2)) == true, "");
123         assert(static_cast<bool>(opt1) == false);
124         assert(static_cast<bool>(opt2) == false);
125         opt1.swap(opt2);
126         assert(static_cast<bool>(opt1) == false);
127         assert(static_cast<bool>(opt2) == false);
128         assert(X::dtor_called == 0);
129     }
130     {
131         optional<X> opt1(1);
132         optional<X> opt2;
133         static_assert(noexcept(opt1.swap(opt2)) == true, "");
134         assert(static_cast<bool>(opt1) == true);
135         assert(*opt1 == 1);
136         assert(static_cast<bool>(opt2) == false);
137         X::dtor_called = 0;
138         opt1.swap(opt2);
139         assert(X::dtor_called == 1);
140         assert(static_cast<bool>(opt1) == false);
141         assert(static_cast<bool>(opt2) == true);
142         assert(*opt2 == 1);
143     }
144     {
145         optional<X> opt1;
146         optional<X> opt2(2);
147         static_assert(noexcept(opt1.swap(opt2)) == true, "");
148         assert(static_cast<bool>(opt1) == false);
149         assert(static_cast<bool>(opt2) == true);
150         assert(*opt2 == 2);
151         X::dtor_called = 0;
152         opt1.swap(opt2);
153         assert(X::dtor_called == 1);
154         assert(static_cast<bool>(opt1) == true);
155         assert(*opt1 == 2);
156         assert(static_cast<bool>(opt2) == false);
157     }
158     {
159         optional<X> opt1(1);
160         optional<X> opt2(2);
161         static_assert(noexcept(opt1.swap(opt2)) == true, "");
162         assert(static_cast<bool>(opt1) == true);
163         assert(*opt1 == 1);
164         assert(static_cast<bool>(opt2) == true);
165         assert(*opt2 == 2);
166         X::dtor_called = 0;
167         opt1.swap(opt2);
168         assert(X::dtor_called == 1);  // from inside std::swap
169         assert(static_cast<bool>(opt1) == true);
170         assert(*opt1 == 2);
171         assert(static_cast<bool>(opt2) == true);
172         assert(*opt2 == 1);
173     }
174     {
175         optional<Y> opt1;
176         optional<Y> opt2;
177         static_assert(noexcept(opt1.swap(opt2)) == false, "");
178         assert(static_cast<bool>(opt1) == false);
179         assert(static_cast<bool>(opt2) == false);
180         opt1.swap(opt2);
181         assert(static_cast<bool>(opt1) == false);
182         assert(static_cast<bool>(opt2) == false);
183         assert(Y::dtor_called == 0);
184     }
185     {
186         optional<Y> opt1(1);
187         optional<Y> opt2;
188         static_assert(noexcept(opt1.swap(opt2)) == false, "");
189         assert(static_cast<bool>(opt1) == true);
190         assert(*opt1 == 1);
191         assert(static_cast<bool>(opt2) == false);
192         Y::dtor_called = 0;
193         opt1.swap(opt2);
194         assert(Y::dtor_called == 1);
195         assert(static_cast<bool>(opt1) == false);
196         assert(static_cast<bool>(opt2) == true);
197         assert(*opt2 == 1);
198     }
199     {
200         optional<Y> opt1;
201         optional<Y> opt2(2);
202         static_assert(noexcept(opt1.swap(opt2)) == false, "");
203         assert(static_cast<bool>(opt1) == false);
204         assert(static_cast<bool>(opt2) == true);
205         assert(*opt2 == 2);
206         Y::dtor_called = 0;
207         opt1.swap(opt2);
208         assert(Y::dtor_called == 1);
209         assert(static_cast<bool>(opt1) == true);
210         assert(*opt1 == 2);
211         assert(static_cast<bool>(opt2) == false);
212     }
213     {
214         optional<Y> opt1(1);
215         optional<Y> opt2(2);
216         static_assert(noexcept(opt1.swap(opt2)) == false, "");
217         assert(static_cast<bool>(opt1) == true);
218         assert(*opt1 == 1);
219         assert(static_cast<bool>(opt2) == true);
220         assert(*opt2 == 2);
221         Y::dtor_called = 0;
222         opt1.swap(opt2);
223         assert(Y::dtor_called == 0);
224         assert(static_cast<bool>(opt1) == true);
225         assert(*opt1 == 2);
226         assert(static_cast<bool>(opt2) == true);
227         assert(*opt2 == 1);
228     }
229     {
230         optional<Z> opt1;
231         optional<Z> opt2;
232         static_assert(noexcept(opt1.swap(opt2)) == false, "");
233         assert(static_cast<bool>(opt1) == false);
234         assert(static_cast<bool>(opt2) == false);
235         opt1.swap(opt2);
236         assert(static_cast<bool>(opt1) == false);
237         assert(static_cast<bool>(opt2) == false);
238     }
239     {
240         optional<Z> opt1;
241         opt1.emplace(1);
242         optional<Z> opt2;
243         static_assert(noexcept(opt1.swap(opt2)) == false, "");
244         assert(static_cast<bool>(opt1) == true);
245         assert(*opt1 == 1);
246         assert(static_cast<bool>(opt2) == false);
247         try
248         {
249             opt1.swap(opt2);
250             assert(false);
251         }
252         catch (int i)
253         {
254             assert(i == 7);
255         }
256         assert(static_cast<bool>(opt1) == true);
257         assert(*opt1 == 1);
258         assert(static_cast<bool>(opt2) == false);
259     }
260     {
261         optional<Z> opt1;
262         optional<Z> opt2;
263         opt2.emplace(2);
264         static_assert(noexcept(opt1.swap(opt2)) == false, "");
265         assert(static_cast<bool>(opt1) == false);
266         assert(static_cast<bool>(opt2) == true);
267         assert(*opt2 == 2);
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) == false);
278         assert(static_cast<bool>(opt2) == true);
279         assert(*opt2 == 2);
280     }
281     {
282         optional<Z> opt1;
283         opt1.emplace(1);
284         optional<Z> opt2;
285         opt2.emplace(2);
286         static_assert(noexcept(opt1.swap(opt2)) == false, "");
287         assert(static_cast<bool>(opt1) == true);
288         assert(*opt1 == 1);
289         assert(static_cast<bool>(opt2) == true);
290         assert(*opt2 == 2);
291         try
292         {
293             opt1.swap(opt2);
294             assert(false);
295         }
296         catch (int i)
297         {
298             assert(i == 6);
299         }
300         assert(static_cast<bool>(opt1) == true);
301         assert(*opt1 == 1);
302         assert(static_cast<bool>(opt2) == true);
303         assert(*opt2 == 2);
304     }
305 #endif  // _LIBCPP_STD_VER > 11
306 }
307