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 // template <class T> void swap(optional<T>& x, optional<T>& y)
13 //     noexcept(noexcept(x.swap(y)));
14 
15 #include <experimental/optional>
16 #include <type_traits>
17 #include <cassert>
18 
19 #if _LIBCPP_STD_VER > 11
20 
21 using std::experimental::optional;
22 
23 class X
24 {
25     int i_;
26 public:
27     static unsigned dtor_called;
X(int i)28     X(int i) : i_(i) {}
29     X(X&& x) = default;
30     X& operator=(X&&) = default;
~X()31     ~X() {++dtor_called;}
32 
operator ==(const X & x,const X & y)33     friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
34 };
35 
36 unsigned X::dtor_called = 0;
37 
38 class Y
39 {
40     int i_;
41 public:
42     static unsigned dtor_called;
Y(int i)43     Y(int i) : i_(i) {}
44     Y(Y&&) = default;
~Y()45     ~Y() {++dtor_called;}
46 
operator ==(const Y & x,const Y & y)47     friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
swap(Y & x,Y & y)48     friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
49 };
50 
51 unsigned Y::dtor_called = 0;
52 
53 class Z
54 {
55     int i_;
56 public:
Z(int i)57     Z(int i) : i_(i) {}
Z(Z &&)58     Z(Z&&) {throw 7;}
59 
operator ==(const Z & x,const Z & y)60     friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
swap(Z & x,Z & y)61     friend void swap(Z& x, Z& y) {throw 6;}
62 };
63 
64 
65 #endif  // _LIBCPP_STD_VER > 11
66 
main()67 int main()
68 {
69 #if _LIBCPP_STD_VER > 11
70     {
71         optional<int> opt1;
72         optional<int> opt2;
73         static_assert(noexcept(swap(opt1, opt2)) == true, "");
74         assert(static_cast<bool>(opt1) == false);
75         assert(static_cast<bool>(opt2) == false);
76         swap(opt1, opt2);
77         assert(static_cast<bool>(opt1) == false);
78         assert(static_cast<bool>(opt2) == false);
79     }
80     {
81         optional<int> opt1(1);
82         optional<int> opt2;
83         static_assert(noexcept(swap(opt1, opt2)) == true, "");
84         assert(static_cast<bool>(opt1) == true);
85         assert(*opt1 == 1);
86         assert(static_cast<bool>(opt2) == false);
87         swap(opt1, opt2);
88         assert(static_cast<bool>(opt1) == false);
89         assert(static_cast<bool>(opt2) == true);
90         assert(*opt2 == 1);
91     }
92     {
93         optional<int> opt1;
94         optional<int> opt2(2);
95         static_assert(noexcept(swap(opt1, opt2)) == true, "");
96         assert(static_cast<bool>(opt1) == false);
97         assert(static_cast<bool>(opt2) == true);
98         assert(*opt2 == 2);
99         swap(opt1, opt2);
100         assert(static_cast<bool>(opt1) == true);
101         assert(*opt1 == 2);
102         assert(static_cast<bool>(opt2) == false);
103     }
104     {
105         optional<int> opt1(1);
106         optional<int> opt2(2);
107         static_assert(noexcept(swap(opt1, opt2)) == true, "");
108         assert(static_cast<bool>(opt1) == true);
109         assert(*opt1 == 1);
110         assert(static_cast<bool>(opt2) == true);
111         assert(*opt2 == 2);
112         swap(opt1, opt2);
113         assert(static_cast<bool>(opt1) == true);
114         assert(*opt1 == 2);
115         assert(static_cast<bool>(opt2) == true);
116         assert(*opt2 == 1);
117     }
118     {
119         optional<X> opt1;
120         optional<X> opt2;
121         static_assert(noexcept(swap(opt1, opt2)) == true, "");
122         assert(static_cast<bool>(opt1) == false);
123         assert(static_cast<bool>(opt2) == false);
124         swap(opt1, opt2);
125         assert(static_cast<bool>(opt1) == false);
126         assert(static_cast<bool>(opt2) == false);
127         assert(X::dtor_called == 0);
128     }
129     {
130         optional<X> opt1(1);
131         optional<X> opt2;
132         static_assert(noexcept(swap(opt1, opt2)) == true, "");
133         assert(static_cast<bool>(opt1) == true);
134         assert(*opt1 == 1);
135         assert(static_cast<bool>(opt2) == false);
136         X::dtor_called = 0;
137         swap(opt1, opt2);
138         assert(X::dtor_called == 1);
139         assert(static_cast<bool>(opt1) == false);
140         assert(static_cast<bool>(opt2) == true);
141         assert(*opt2 == 1);
142     }
143     {
144         optional<X> opt1;
145         optional<X> opt2(2);
146         static_assert(noexcept(swap(opt1, opt2)) == true, "");
147         assert(static_cast<bool>(opt1) == false);
148         assert(static_cast<bool>(opt2) == true);
149         assert(*opt2 == 2);
150         X::dtor_called = 0;
151         swap(opt1, opt2);
152         assert(X::dtor_called == 1);
153         assert(static_cast<bool>(opt1) == true);
154         assert(*opt1 == 2);
155         assert(static_cast<bool>(opt2) == false);
156     }
157     {
158         optional<X> opt1(1);
159         optional<X> opt2(2);
160         static_assert(noexcept(swap(opt1, opt2)) == true, "");
161         assert(static_cast<bool>(opt1) == true);
162         assert(*opt1 == 1);
163         assert(static_cast<bool>(opt2) == true);
164         assert(*opt2 == 2);
165         X::dtor_called = 0;
166         swap(opt1, opt2);
167         assert(X::dtor_called == 1);  // from inside std::swap
168         assert(static_cast<bool>(opt1) == true);
169         assert(*opt1 == 2);
170         assert(static_cast<bool>(opt2) == true);
171         assert(*opt2 == 1);
172     }
173     {
174         optional<Y> opt1;
175         optional<Y> opt2;
176         static_assert(noexcept(swap(opt1, opt2)) == false, "");
177         assert(static_cast<bool>(opt1) == false);
178         assert(static_cast<bool>(opt2) == false);
179         swap(opt1, opt2);
180         assert(static_cast<bool>(opt1) == false);
181         assert(static_cast<bool>(opt2) == false);
182         assert(Y::dtor_called == 0);
183     }
184     {
185         optional<Y> opt1(1);
186         optional<Y> opt2;
187         static_assert(noexcept(swap(opt1, opt2)) == false, "");
188         assert(static_cast<bool>(opt1) == true);
189         assert(*opt1 == 1);
190         assert(static_cast<bool>(opt2) == false);
191         Y::dtor_called = 0;
192         swap(opt1, opt2);
193         assert(Y::dtor_called == 1);
194         assert(static_cast<bool>(opt1) == false);
195         assert(static_cast<bool>(opt2) == true);
196         assert(*opt2 == 1);
197     }
198     {
199         optional<Y> opt1;
200         optional<Y> opt2(2);
201         static_assert(noexcept(swap(opt1, opt2)) == false, "");
202         assert(static_cast<bool>(opt1) == false);
203         assert(static_cast<bool>(opt2) == true);
204         assert(*opt2 == 2);
205         Y::dtor_called = 0;
206         swap(opt1, opt2);
207         assert(Y::dtor_called == 1);
208         assert(static_cast<bool>(opt1) == true);
209         assert(*opt1 == 2);
210         assert(static_cast<bool>(opt2) == false);
211     }
212     {
213         optional<Y> opt1(1);
214         optional<Y> opt2(2);
215         static_assert(noexcept(swap(opt1, opt2)) == false, "");
216         assert(static_cast<bool>(opt1) == true);
217         assert(*opt1 == 1);
218         assert(static_cast<bool>(opt2) == true);
219         assert(*opt2 == 2);
220         Y::dtor_called = 0;
221         swap(opt1, opt2);
222         assert(Y::dtor_called == 0);
223         assert(static_cast<bool>(opt1) == true);
224         assert(*opt1 == 2);
225         assert(static_cast<bool>(opt2) == true);
226         assert(*opt2 == 1);
227     }
228     {
229         optional<Z> opt1;
230         optional<Z> opt2;
231         static_assert(noexcept(swap(opt1, opt2)) == false, "");
232         assert(static_cast<bool>(opt1) == false);
233         assert(static_cast<bool>(opt2) == false);
234         swap(opt1, opt2);
235         assert(static_cast<bool>(opt1) == false);
236         assert(static_cast<bool>(opt2) == false);
237     }
238     {
239         optional<Z> opt1;
240         opt1.emplace(1);
241         optional<Z> opt2;
242         static_assert(noexcept(swap(opt1, opt2)) == false, "");
243         assert(static_cast<bool>(opt1) == true);
244         assert(*opt1 == 1);
245         assert(static_cast<bool>(opt2) == false);
246         try
247         {
248             swap(opt1, 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(swap(opt1, opt2)) == false, "");
264         assert(static_cast<bool>(opt1) == false);
265         assert(static_cast<bool>(opt2) == true);
266         assert(*opt2 == 2);
267         try
268         {
269             swap(opt1, 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(swap(opt1, 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             swap(opt1, 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  // _LIBCPP_STD_VER > 11
305 }
306