]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/variant/run.cc
3ca375d374e592e8f3dd6c32835ed627fe9c5f15
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / variant / run.cc
1 // { dg-options "-std=gnu++17" }
2 // { dg-do run }
3
4 // Copyright (C) 2016-2019 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3. If not see
19 // <http://www.gnu.org/licenses/>.
20
21 #include <variant>
22 #include <string>
23 #include <vector>
24 #include <unordered_set>
25 #include <memory_resource>
26 #include <testsuite_hooks.h>
27
28 using namespace std;
29
30 struct AlwaysThrow
31 {
32 AlwaysThrow() = default;
33
34 AlwaysThrow(const AlwaysThrow&)
35 { throw nullptr; }
36
37 AlwaysThrow(AlwaysThrow&&)
38 { throw nullptr; }
39
40 AlwaysThrow& operator=(const AlwaysThrow&)
41 {
42 throw nullptr;
43 return *this;
44 }
45
46 AlwaysThrow& operator=(AlwaysThrow&&)
47 {
48 throw nullptr;
49 return *this;
50 }
51
52 bool operator<(const AlwaysThrow&) const { VERIFY(false); }
53 bool operator<=(const AlwaysThrow&) const { VERIFY(false); }
54 bool operator==(const AlwaysThrow&) const { VERIFY(false); }
55 bool operator!=(const AlwaysThrow&) const { VERIFY(false); }
56 bool operator>=(const AlwaysThrow&) const { VERIFY(false); }
57 bool operator>(const AlwaysThrow&) const { VERIFY(false); }
58 };
59
60 void default_ctor()
61 {
62 variant<monostate, string> v;
63 VERIFY(holds_alternative<monostate>(v));
64 }
65
66 void copy_ctor()
67 {
68 variant<monostate, string> v("a");
69 VERIFY(holds_alternative<string>(v));
70 variant<monostate, string> u(v);
71 VERIFY(holds_alternative<string>(u));
72 VERIFY(get<string>(u) == "a");
73 }
74
75 void move_ctor()
76 {
77 variant<monostate, string> v("a");
78 VERIFY(holds_alternative<string>(v));
79 variant<monostate, string> u(std::move(v));
80 VERIFY(holds_alternative<string>(u));
81 VERIFY(get<string>(u) == "a");
82 VERIFY(holds_alternative<string>(v));
83 }
84
85 void arbitrary_ctor()
86 {
87 variant<int, string> v("a");
88 VERIFY(holds_alternative<string>(v));
89 VERIFY(get<1>(v) == "a");
90 }
91
92 struct ThrowingMoveCtorThrowsCopyCtor
93 {
94 ThrowingMoveCtorThrowsCopyCtor() noexcept = default;
95 ThrowingMoveCtorThrowsCopyCtor(ThrowingMoveCtorThrowsCopyCtor&&) {}
96 ThrowingMoveCtorThrowsCopyCtor(ThrowingMoveCtorThrowsCopyCtor const&)
97 {
98 throw 0;
99 }
100
101 ThrowingMoveCtorThrowsCopyCtor& operator=(ThrowingMoveCtorThrowsCopyCtor&&) noexcept
102 = default;
103 ThrowingMoveCtorThrowsCopyCtor& operator=(ThrowingMoveCtorThrowsCopyCtor const&) noexcept
104 = default;
105 };
106
107 void copy_assign()
108 {
109 variant<monostate, string> v("a");
110 VERIFY(holds_alternative<string>(v));
111 variant<monostate, string> u;
112 u = v;
113 VERIFY(holds_alternative<string>(u));
114 VERIFY(get<string>(u) == "a");
115 {
116 std::variant<int, ThrowingMoveCtorThrowsCopyCtor> v1,
117 v2 = ThrowingMoveCtorThrowsCopyCtor();
118 bool should_throw = false;
119 try
120 {
121 v1 = v2;
122 }
123 catch(int)
124 {
125 should_throw = true;
126 }
127 VERIFY(should_throw);
128 }
129 }
130
131 void move_assign()
132 {
133 variant<monostate, string> v("a");
134 VERIFY(holds_alternative<string>(v));
135 variant<monostate, string> u;
136 u = std::move(v);
137 VERIFY(holds_alternative<string>(u));
138 VERIFY(get<string>(u) == "a");
139 VERIFY(holds_alternative<string>(v));
140 }
141
142 void arbitrary_assign()
143 {
144 variant<int, string> v;
145 v = "a";
146
147 VERIFY(holds_alternative<string>(variant<int, string>("a")));
148 VERIFY(get<1>(v) == "a");
149 }
150
151 void dtor()
152 {
153 struct A {
154 A(int& called) : called(called) {}
155 ~A() {
156 called++;
157 }
158 int& called;
159 };
160 {
161 int called = 0;
162 { variant<string, A> a(in_place_index<1>, called); }
163 VERIFY(called == 1);
164 }
165 {
166 int called = 0;
167 { variant<string, A> a(in_place_index<0>); }
168 VERIFY(called == 0);
169 }
170 }
171
172 void in_place_index_ctor()
173 {
174 {
175 variant<int, string> v(in_place_index<1>, "a");
176 VERIFY(holds_alternative<string>(v));
177 VERIFY(get<1>(v) == "a");
178 }
179 {
180 variant<int, string> v(in_place_index<1>, {'a', 'b'});
181 VERIFY(holds_alternative<string>(v));
182 VERIFY(get<1>(v) == "ab");
183 }
184 }
185
186 void in_place_type_ctor()
187 {
188 {
189 variant<int, string> v(in_place_type<string>, "a");
190 VERIFY(holds_alternative<string>(v));
191 VERIFY(get<1>(v) == "a");
192 }
193 {
194 variant<int, string> v(in_place_type<string>, {'a', 'b'});
195 VERIFY(holds_alternative<string>(v));
196 VERIFY(get<1>(v) == "ab");
197 }
198 }
199
200 void emplace()
201 {
202 variant<int, string> v;
203 v.emplace<0>(1);
204 VERIFY(get<0>(v) == 1);
205 v.emplace<string>("a");
206 VERIFY(get<string>(v) == "a");
207 v.emplace<1>({'a', 'b'});
208 VERIFY(get<1>(v) == "ab");
209 v.emplace<string>({'a', 'c'});
210 VERIFY(get<string>(v) == "ac");
211 {
212 variant<int, AlwaysThrow> v;
213 AlwaysThrow a;
214 try { v.emplace<1>(a); } catch (nullptr_t) { }
215 VERIFY(v.valueless_by_exception());
216 v.emplace<0>(42);
217 VERIFY(!v.valueless_by_exception());
218 }
219 {
220 variant<int, AlwaysThrow> v;
221 try { v.emplace<1>(AlwaysThrow{}); } catch (nullptr_t) { }
222 VERIFY(v.valueless_by_exception());
223 v.emplace<0>(42);
224 VERIFY(!v.valueless_by_exception());
225 }
226 VERIFY(&v.emplace<0>(1) == &std::get<0>(v));
227 VERIFY(&v.emplace<int>(1) == &std::get<int>(v));
228 VERIFY(&v.emplace<1>("a") == &std::get<1>(v));
229 VERIFY(&v.emplace<string>("a") == &std::get<string>(v));
230 {
231 variant<vector<int>> v;
232 VERIFY(&v.emplace<0>({1,2,3}) == &std::get<0>(v));
233 VERIFY(&v.emplace<vector<int>>({1,2,3}) == &std::get<vector<int>>(v));
234 }
235 }
236
237 void test_get()
238 {
239 VERIFY(get<1>(variant<int, string>("a")) == "a");
240 VERIFY(get<string>(variant<int, string>("a")) == "a");
241 {
242 bool caught = false;
243
244 try
245 {
246 get<0>(variant<int, string>("a"));
247 }
248 catch (const bad_variant_access&)
249 {
250 caught = true;
251 }
252 VERIFY(caught);
253 }
254 {
255 bool caught = false;
256
257 try
258 {
259 get<int>(variant<int, string>("a"));
260 }
261 catch (const bad_variant_access&)
262 {
263 caught = true;
264 }
265 VERIFY(caught);
266 }
267 }
268
269 void test_relational()
270 {
271 VERIFY((variant<int, string>(2) < variant<int, string>(3)));
272 VERIFY((variant<int, string>(3) == variant<int, string>(3)));
273 VERIFY((variant<int, string>(3) > variant<int, string>(2)));
274 VERIFY((variant<int, string>(3) <= variant<int, string>(3)));
275 VERIFY((variant<int, string>(2) <= variant<int, string>(3)));
276 VERIFY((variant<int, string>(3) >= variant<int, string>(3)));
277 VERIFY((variant<int, string>(3) >= variant<int, string>(2)));
278 VERIFY((variant<int, string>(2) != variant<int, string>(3)));
279
280 VERIFY((variant<int, string>(2) < variant<int, string>("a")));
281 VERIFY((variant<string, int>(2) > variant<string, int>("a")));
282
283 {
284 variant<int, AlwaysThrow> v, w;
285 try
286 {
287 AlwaysThrow a;
288 v = a;
289 }
290 catch (nullptr_t) { }
291 VERIFY(v.valueless_by_exception());
292 VERIFY(v < w);
293 VERIFY(v <= w);
294 VERIFY(!(v == w));
295 VERIFY(v == v);
296 VERIFY(v != w);
297 VERIFY(w > v);
298 VERIFY(w >= v);
299 }
300 }
301
302 void test_swap()
303 {
304 variant<int, string> a("a"), b("b");
305 a.swap(b);
306 VERIFY(get<1>(a) == "b");
307 VERIFY(get<1>(b) == "a");
308 swap(a, b);
309 VERIFY(get<1>(a) == "a");
310 VERIFY(get<1>(b) == "b");
311 }
312
313 void test_visit()
314 {
315 {
316 struct Visitor
317 {
318 int operator()(int, float) {
319 return 0;
320 }
321 int operator()(int, double) {
322 return 1;
323 }
324 int operator()(char, float) {
325 return 2;
326 }
327 int operator()(char, double) {
328 return 3;
329 }
330 int operator()(int, float) const {
331 return 5;
332 }
333 int operator()(int, double) const {
334 return 6;
335 }
336 int operator()(char, float) const {
337 return 7;
338 }
339 int operator()(char, double) const {
340 return 8;
341 }
342 } visitor1;
343 VERIFY(visit(visitor1, variant<int, char>(1), variant<float, double>(1.0f)) == 0);
344 VERIFY(visit(visitor1, variant<int, char>(1), variant<float, double>(1.0)) == 1);
345 VERIFY(visit(visitor1, variant<int, char>('a'), variant<float, double>(1.0f)) == 2);
346 VERIFY(visit(visitor1, variant<int, char>('a'), variant<float, double>(1.0)) == 3);
347
348 const auto& visitor2 = visitor1;
349 VERIFY(visit(visitor2, variant<int, char>(1), variant<float, double>(1.0f)) == 5);
350 VERIFY(visit(visitor2, variant<int, char>(1), variant<float, double>(1.0)) == 6);
351 VERIFY(visit(visitor2, variant<int, char>('a'), variant<float, double>(1.0f)) == 7);
352 VERIFY(visit(visitor2, variant<int, char>('a'), variant<float, double>(1.0)) == 8);
353 }
354
355 {
356 struct Visitor
357 {
358 int operator()(int, float) && {
359 return 0;
360 }
361 int operator()(int, double) && {
362 return 1;
363 }
364 int operator()(char, float) && {
365 return 2;
366 }
367 int operator()(char, double) && {
368 return 3;
369 }
370 };
371 VERIFY(visit(Visitor{}, variant<int, char>(1), variant<float, double>(1.0f)) == 0);
372 VERIFY(visit(Visitor{}, variant<int, char>(1), variant<float, double>(1.0)) == 1);
373 VERIFY(visit(Visitor{}, variant<int, char>('a'), variant<float, double>(1.0f)) == 2);
374 VERIFY(visit(Visitor{}, variant<int, char>('a'), variant<float, double>(1.0)) == 3);
375 }
376 }
377
378 void test_hash()
379 {
380 unordered_set<variant<int, pmr::string>> s;
381 VERIFY(s.emplace(3).second);
382 VERIFY(s.emplace("asdf").second);
383 VERIFY(s.emplace().second);
384 VERIFY(s.size() == 3);
385 VERIFY(!s.emplace(3).second);
386 VERIFY(!s.emplace("asdf").second);
387 VERIFY(!s.emplace().second);
388 VERIFY(s.size() == 3);
389 {
390 struct A
391 {
392 operator pmr::string()
393 {
394 throw nullptr;
395 }
396 };
397 variant<int, pmr::string> v;
398 try
399 {
400 v.emplace<1>(A{});
401 }
402 catch (nullptr_t)
403 {
404 }
405 VERIFY(v.valueless_by_exception());
406 VERIFY(s.insert(v).second);
407 VERIFY(s.size() == 4);
408 VERIFY(!s.insert(v).second);
409 }
410 }
411
412 void test_valueless_by_exception()
413 {
414 {
415 AlwaysThrow a;
416 bool caught = false;
417 try
418 {
419 variant<int, AlwaysThrow> v(a);
420 }
421 catch (nullptr_t)
422 {
423 caught = true;
424 }
425 VERIFY(caught);
426 }
427 {
428 AlwaysThrow a;
429 bool caught = false;
430 try
431 {
432 variant<int, AlwaysThrow> v(a);
433 }
434 catch (nullptr_t)
435 {
436 caught = true;
437 }
438 VERIFY(caught);
439 }
440 {
441 variant<int, AlwaysThrow> v;
442 bool caught = false;
443 try
444 {
445 AlwaysThrow a;
446 v = a;
447 }
448 catch (nullptr_t)
449 {
450 caught = true;
451 }
452 VERIFY(caught);
453 VERIFY(v.valueless_by_exception());
454 }
455 {
456 variant<int, AlwaysThrow> v;
457 bool caught = false;
458 try
459 {
460 v = AlwaysThrow{};
461 }
462 catch (nullptr_t)
463 {
464 caught = true;
465 }
466 VERIFY(caught);
467 VERIFY(v.valueless_by_exception());
468 }
469 }
470
471 int main()
472 {
473 default_ctor();
474 copy_ctor();
475 move_ctor();
476 arbitrary_ctor();
477 in_place_index_ctor();
478 in_place_type_ctor();
479 copy_assign();
480 move_assign();
481 arbitrary_assign();
482 dtor();
483 emplace();
484 test_get();
485 test_relational();
486 test_swap();
487 test_visit();
488 test_hash();
489 test_valueless_by_exception();
490 }