• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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