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
21using std::experimental::optional;
22
23class X
24{
25    int i_;
26public:
27    static unsigned dtor_called;
28    X(int i) : i_(i) {}
29    X(X&& x) = default;
30    X& operator=(X&&) = default;
31    ~X() {++dtor_called;}
32
33    friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
34};
35
36unsigned X::dtor_called = 0;
37
38class Y
39{
40    int i_;
41public:
42    static unsigned dtor_called;
43    Y(int i) : i_(i) {}
44    Y(Y&&) = default;
45    ~Y() {++dtor_called;}
46
47    friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
48    friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
49};
50
51unsigned Y::dtor_called = 0;
52
53class Z
54{
55    int i_;
56public:
57    Z(int i) : i_(i) {}
58    Z(Z&&) {throw 7;}
59
60    friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
61    friend void swap(Z& x, Z& y) {throw 6;}
62};
63
64
65#endif  // _LIBCPP_STD_VER > 11
66
67int 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