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// UNSUPPORTED: c++98, c++03, c++11, c++14
11// <optional>
12
13// void swap(optional&)
14//     noexcept(is_nothrow_move_constructible<T>::value &&
15//              is_nothrow_swappable<T>::value)
16
17#include <optional>
18#include <type_traits>
19#include <cassert>
20
21#include "test_macros.h"
22#include "archetypes.hpp"
23
24using std::optional;
25
26class X
27{
28    int i_;
29public:
30    static unsigned dtor_called;
31    X(int i) : i_(i) {}
32    X(X&& x) = default;
33    X& operator=(X&&) = default;
34    ~X() {++dtor_called;}
35
36    friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
37};
38
39unsigned X::dtor_called = 0;
40
41class Y
42{
43    int i_;
44public:
45    static unsigned dtor_called;
46    Y(int i) : i_(i) {}
47    Y(Y&&) = default;
48    ~Y() {++dtor_called;}
49
50    friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
51    friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
52};
53
54unsigned Y::dtor_called = 0;
55
56class Z
57{
58    int i_;
59public:
60    Z(int i) : i_(i) {}
61    Z(Z&&) {TEST_THROW(7);}
62
63    friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
64    friend void swap(Z&, Z&) {TEST_THROW(6);}
65};
66
67
68int main()
69{
70    {
71        optional<int> opt1;
72        optional<int> opt2;
73        static_assert(noexcept(opt1.swap(opt2)) == true, "");
74        assert(static_cast<bool>(opt1) == false);
75        assert(static_cast<bool>(opt2) == false);
76        opt1.swap(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(opt1.swap(opt2)) == true, "");
84        assert(static_cast<bool>(opt1) == true);
85        assert(*opt1 == 1);
86        assert(static_cast<bool>(opt2) == false);
87        opt1.swap(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(opt1.swap(opt2)) == true, "");
96        assert(static_cast<bool>(opt1) == false);
97        assert(static_cast<bool>(opt2) == true);
98        assert(*opt2 == 2);
99        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(opt2)) == true, "");
122        assert(static_cast<bool>(opt1) == false);
123        assert(static_cast<bool>(opt2) == false);
124        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(opt2)) == false, "");
177        assert(static_cast<bool>(opt1) == false);
178        assert(static_cast<bool>(opt2) == false);
179        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(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        opt1.swap(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(opt1.swap(opt2)) == false, "");
232        assert(static_cast<bool>(opt1) == false);
233        assert(static_cast<bool>(opt2) == false);
234        opt1.swap(opt2);
235        assert(static_cast<bool>(opt1) == false);
236        assert(static_cast<bool>(opt2) == false);
237    }
238#ifndef TEST_HAS_NO_EXCEPTIONS
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
306}
307