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;
X(int i)29 X(int i) : i_(i) {}
30 X(X&& x) = default;
31 X& operator=(X&&) = default;
~X()32 ~X() {++dtor_called;}
33
operator ==(const X & x,const X & y)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;
Y(int i)44 Y(int i) : i_(i) {}
45 Y(Y&&) = default;
~Y()46 ~Y() {++dtor_called;}
47
operator ==(const Y & x,const Y & y)48 friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
swap(Y & x,Y & y)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:
Z(int i)58 Z(int i) : i_(i) {}
Z(Z &&)59 Z(Z&&) {throw 7;}
60
operator ==(const Z & x,const Z & y)61 friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
swap(Z & x,Z & y)62 friend void swap(Z& x, Z& y) {throw 6;}
63 };
64
65
66 #endif // _LIBCPP_STD_VER > 11
67
main()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