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 // template <class T> void swap(optional<T>& x, optional<T>& y)
14 // noexcept(noexcept(x.swap(y)));
15
16 #include <optional>
17 #include <type_traits>
18 #include <cassert>
19
20 #include "test_macros.h"
21 #include "archetypes.hpp"
22
23 using std::optional;
24
25 class X
26 {
27 int i_;
28 public:
29 static unsigned dtor_called;
X(int i)30 X(int i) : i_(i) {}
31 X(X&& x) = default;
32 X& operator=(X&&) = default;
~X()33 ~X() {++dtor_called;}
34
operator ==(const X & x,const X & y)35 friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
36 };
37
38 unsigned X::dtor_called = 0;
39
40 class Y
41 {
42 int i_;
43 public:
44 static unsigned dtor_called;
Y(int i)45 Y(int i) : i_(i) {}
46 Y(Y&&) = default;
~Y()47 ~Y() {++dtor_called;}
48
operator ==(const Y & x,const Y & y)49 friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
swap(Y & x,Y & y)50 friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
51 };
52
53 unsigned Y::dtor_called = 0;
54
55 class Z
56 {
57 int i_;
58 public:
Z(int i)59 Z(int i) : i_(i) {}
Z(Z &&)60 Z(Z&&) { TEST_THROW(7);}
61
operator ==(const Z & x,const Z & y)62 friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
swap(Z &,Z &)63 friend void swap(Z&, Z&) { TEST_THROW(6);}
64 };
65
66
67 struct NonSwappable {
68 NonSwappable(NonSwappable const&) = delete;
69 };
70 void swap(NonSwappable&, NonSwappable&) = delete;
71
test_swap_sfinae()72 void test_swap_sfinae() {
73 using std::optional;
74 {
75 using T = TestTypes::TestType;
76 static_assert(std::is_swappable_v<optional<T>>, "");
77 }
78 {
79 using T = TestTypes::MoveOnly;
80 static_assert(std::is_swappable_v<optional<T>>, "");
81 }
82 {
83 using T = TestTypes::Copyable;
84 static_assert(std::is_swappable_v<optional<T>>, "");
85 }
86 {
87 using T = TestTypes::NoCtors;
88 static_assert(!std::is_swappable_v<optional<T>>, "");
89 }
90 {
91 using T = NonSwappable;
92 static_assert(!std::is_swappable_v<optional<T>>, "");
93 }
94 {
95 // Even thought CopyOnly has deleted move operations, those operations
96 // cause optional<CopyOnly> to have implicitly deleted move operations
97 // that decay into copies.
98 using T = TestTypes::CopyOnly;
99 using Opt = optional<T>;
100 T::reset();
101 Opt L(101), R(42);
102 T::reset_constructors();
103 std::swap(L, R);
104 assert(L->value == 42);
105 assert(R->value == 101);
106 assert(T::copy_constructed == 1);
107 assert(T::constructed == T::copy_constructed);
108 assert(T::assigned == 2);
109 assert(T::assigned == T::copy_assigned);
110 }
111 }
112
main()113 int main()
114 {
115 test_swap_sfinae();
116 {
117 optional<int> opt1;
118 optional<int> opt2;
119 static_assert(noexcept(swap(opt1, opt2)) == true, "");
120 assert(static_cast<bool>(opt1) == false);
121 assert(static_cast<bool>(opt2) == false);
122 swap(opt1, opt2);
123 assert(static_cast<bool>(opt1) == false);
124 assert(static_cast<bool>(opt2) == false);
125 }
126 {
127 optional<int> opt1(1);
128 optional<int> opt2;
129 static_assert(noexcept(swap(opt1, opt2)) == true, "");
130 assert(static_cast<bool>(opt1) == true);
131 assert(*opt1 == 1);
132 assert(static_cast<bool>(opt2) == false);
133 swap(opt1, opt2);
134 assert(static_cast<bool>(opt1) == false);
135 assert(static_cast<bool>(opt2) == true);
136 assert(*opt2 == 1);
137 }
138 {
139 optional<int> opt1;
140 optional<int> opt2(2);
141 static_assert(noexcept(swap(opt1, opt2)) == true, "");
142 assert(static_cast<bool>(opt1) == false);
143 assert(static_cast<bool>(opt2) == true);
144 assert(*opt2 == 2);
145 swap(opt1, opt2);
146 assert(static_cast<bool>(opt1) == true);
147 assert(*opt1 == 2);
148 assert(static_cast<bool>(opt2) == false);
149 }
150 {
151 optional<int> opt1(1);
152 optional<int> opt2(2);
153 static_assert(noexcept(swap(opt1, opt2)) == true, "");
154 assert(static_cast<bool>(opt1) == true);
155 assert(*opt1 == 1);
156 assert(static_cast<bool>(opt2) == true);
157 assert(*opt2 == 2);
158 swap(opt1, opt2);
159 assert(static_cast<bool>(opt1) == true);
160 assert(*opt1 == 2);
161 assert(static_cast<bool>(opt2) == true);
162 assert(*opt2 == 1);
163 }
164 {
165 optional<X> opt1;
166 optional<X> opt2;
167 static_assert(noexcept(swap(opt1, opt2)) == true, "");
168 assert(static_cast<bool>(opt1) == false);
169 assert(static_cast<bool>(opt2) == false);
170 swap(opt1, opt2);
171 assert(static_cast<bool>(opt1) == false);
172 assert(static_cast<bool>(opt2) == false);
173 assert(X::dtor_called == 0);
174 }
175 {
176 optional<X> opt1(1);
177 optional<X> opt2;
178 static_assert(noexcept(swap(opt1, opt2)) == true, "");
179 assert(static_cast<bool>(opt1) == true);
180 assert(*opt1 == 1);
181 assert(static_cast<bool>(opt2) == false);
182 X::dtor_called = 0;
183 swap(opt1, opt2);
184 assert(X::dtor_called == 1);
185 assert(static_cast<bool>(opt1) == false);
186 assert(static_cast<bool>(opt2) == true);
187 assert(*opt2 == 1);
188 }
189 {
190 optional<X> opt1;
191 optional<X> opt2(2);
192 static_assert(noexcept(swap(opt1, opt2)) == true, "");
193 assert(static_cast<bool>(opt1) == false);
194 assert(static_cast<bool>(opt2) == true);
195 assert(*opt2 == 2);
196 X::dtor_called = 0;
197 swap(opt1, opt2);
198 assert(X::dtor_called == 1);
199 assert(static_cast<bool>(opt1) == true);
200 assert(*opt1 == 2);
201 assert(static_cast<bool>(opt2) == false);
202 }
203 {
204 optional<X> opt1(1);
205 optional<X> opt2(2);
206 static_assert(noexcept(swap(opt1, opt2)) == true, "");
207 assert(static_cast<bool>(opt1) == true);
208 assert(*opt1 == 1);
209 assert(static_cast<bool>(opt2) == true);
210 assert(*opt2 == 2);
211 X::dtor_called = 0;
212 swap(opt1, opt2);
213 assert(X::dtor_called == 1); // from inside std::swap
214 assert(static_cast<bool>(opt1) == true);
215 assert(*opt1 == 2);
216 assert(static_cast<bool>(opt2) == true);
217 assert(*opt2 == 1);
218 }
219 {
220 optional<Y> opt1;
221 optional<Y> opt2;
222 static_assert(noexcept(swap(opt1, opt2)) == false, "");
223 assert(static_cast<bool>(opt1) == false);
224 assert(static_cast<bool>(opt2) == false);
225 swap(opt1, opt2);
226 assert(static_cast<bool>(opt1) == false);
227 assert(static_cast<bool>(opt2) == false);
228 assert(Y::dtor_called == 0);
229 }
230 {
231 optional<Y> opt1(1);
232 optional<Y> opt2;
233 static_assert(noexcept(swap(opt1, opt2)) == false, "");
234 assert(static_cast<bool>(opt1) == true);
235 assert(*opt1 == 1);
236 assert(static_cast<bool>(opt2) == false);
237 Y::dtor_called = 0;
238 swap(opt1, opt2);
239 assert(Y::dtor_called == 1);
240 assert(static_cast<bool>(opt1) == false);
241 assert(static_cast<bool>(opt2) == true);
242 assert(*opt2 == 1);
243 }
244 {
245 optional<Y> opt1;
246 optional<Y> opt2(2);
247 static_assert(noexcept(swap(opt1, opt2)) == false, "");
248 assert(static_cast<bool>(opt1) == false);
249 assert(static_cast<bool>(opt2) == true);
250 assert(*opt2 == 2);
251 Y::dtor_called = 0;
252 swap(opt1, opt2);
253 assert(Y::dtor_called == 1);
254 assert(static_cast<bool>(opt1) == true);
255 assert(*opt1 == 2);
256 assert(static_cast<bool>(opt2) == false);
257 }
258 {
259 optional<Y> opt1(1);
260 optional<Y> opt2(2);
261 static_assert(noexcept(swap(opt1, opt2)) == false, "");
262 assert(static_cast<bool>(opt1) == true);
263 assert(*opt1 == 1);
264 assert(static_cast<bool>(opt2) == true);
265 assert(*opt2 == 2);
266 Y::dtor_called = 0;
267 swap(opt1, opt2);
268 assert(Y::dtor_called == 0);
269 assert(static_cast<bool>(opt1) == true);
270 assert(*opt1 == 2);
271 assert(static_cast<bool>(opt2) == true);
272 assert(*opt2 == 1);
273 }
274 {
275 optional<Z> opt1;
276 optional<Z> opt2;
277 static_assert(noexcept(swap(opt1, opt2)) == false, "");
278 assert(static_cast<bool>(opt1) == false);
279 assert(static_cast<bool>(opt2) == false);
280 swap(opt1, opt2);
281 assert(static_cast<bool>(opt1) == false);
282 assert(static_cast<bool>(opt2) == false);
283 }
284 #ifndef TEST_HAS_NO_EXCEPTIONS
285 {
286 optional<Z> opt1;
287 opt1.emplace(1);
288 optional<Z> opt2;
289 static_assert(noexcept(swap(opt1, opt2)) == false, "");
290 assert(static_cast<bool>(opt1) == true);
291 assert(*opt1 == 1);
292 assert(static_cast<bool>(opt2) == false);
293 try
294 {
295 swap(opt1, opt2);
296 assert(false);
297 }
298 catch (int i)
299 {
300 assert(i == 7);
301 }
302 assert(static_cast<bool>(opt1) == true);
303 assert(*opt1 == 1);
304 assert(static_cast<bool>(opt2) == false);
305 }
306 {
307 optional<Z> opt1;
308 optional<Z> opt2;
309 opt2.emplace(2);
310 static_assert(noexcept(swap(opt1, opt2)) == false, "");
311 assert(static_cast<bool>(opt1) == false);
312 assert(static_cast<bool>(opt2) == true);
313 assert(*opt2 == 2);
314 try
315 {
316 swap(opt1, opt2);
317 assert(false);
318 }
319 catch (int i)
320 {
321 assert(i == 7);
322 }
323 assert(static_cast<bool>(opt1) == false);
324 assert(static_cast<bool>(opt2) == true);
325 assert(*opt2 == 2);
326 }
327 {
328 optional<Z> opt1;
329 opt1.emplace(1);
330 optional<Z> opt2;
331 opt2.emplace(2);
332 static_assert(noexcept(swap(opt1, opt2)) == false, "");
333 assert(static_cast<bool>(opt1) == true);
334 assert(*opt1 == 1);
335 assert(static_cast<bool>(opt2) == true);
336 assert(*opt2 == 2);
337 try
338 {
339 swap(opt1, opt2);
340 assert(false);
341 }
342 catch (int i)
343 {
344 assert(i == 6);
345 }
346 assert(static_cast<bool>(opt1) == true);
347 assert(*opt1 == 1);
348 assert(static_cast<bool>(opt2) == true);
349 assert(*opt2 == 2);
350 }
351 #endif // TEST_HAS_NO_EXCEPTIONS
352 }
353