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
22using std::experimental::optional;
23
24class X
25{
26    int i_;
27public:
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
37unsigned X::dtor_called = 0;
38
39class Y
40{
41    int i_;
42public:
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
52unsigned Y::dtor_called = 0;
53
54class Z
55{
56    int i_;
57public:
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
68int 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