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