]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/variant/run.cc
Implement LWG 2857, {variant,optional,any}::emplace should return the constructed...
[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-2017 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 <testsuite_hooks.h>
26
27 using namespace std;
28
29 struct AlwaysThrow
30 {
31 AlwaysThrow() = default;
32
33 AlwaysThrow(const AlwaysThrow&)
34 { throw nullptr; }
35
36 AlwaysThrow(AlwaysThrow&&)
37 { throw nullptr; }
38
39 AlwaysThrow& operator=(const AlwaysThrow&)
40 {
41 throw nullptr;
42 return *this;
43 }
44
45 AlwaysThrow& operator=(AlwaysThrow&&)
46 {
47 throw nullptr;
48 return *this;
49 }
50
51 bool operator<(const AlwaysThrow&) const { VERIFY(false); }
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 };
58
59 void default_ctor()
60 {
61 variant<monostate, string> v;
62 VERIFY(holds_alternative<monostate>(v));
63 }
64
65 void copy_ctor()
66 {
67 variant<monostate, string> v("a");
68 VERIFY(holds_alternative<string>(v));
69 variant<monostate, string> u(v);
70 VERIFY(holds_alternative<string>(u));
71 VERIFY(get<string>(u) == "a");
72 }
73
74 void move_ctor()
75 {
76 variant<monostate, string> v("a");
77 VERIFY(holds_alternative<string>(v));
78 variant<monostate, string> u(std::move(v));
79 VERIFY(holds_alternative<string>(u));
80 VERIFY(get<string>(u) == "a");
81 VERIFY(holds_alternative<string>(v));
82 }
83
84 void arbitrary_ctor()
85 {
86 variant<int, string> v("a");
87 VERIFY(holds_alternative<string>(v));
88 VERIFY(get<1>(v) == "a");
89 }
90
91 void copy_assign()
92 {
93 variant<monostate, string> v("a");
94 VERIFY(holds_alternative<string>(v));
95 variant<monostate, string> u;
96 u = v;
97 VERIFY(holds_alternative<string>(u));
98 VERIFY(get<string>(u) == "a");
99 }
100
101 void move_assign()
102 {
103 variant<monostate, string> v("a");
104 VERIFY(holds_alternative<string>(v));
105 variant<monostate, string> u;
106 u = std::move(v);
107 VERIFY(holds_alternative<string>(u));
108 VERIFY(get<string>(u) == "a");
109 VERIFY(holds_alternative<string>(v));
110 }
111
112 void arbitrary_assign()
113 {
114 variant<int, string> v;
115 v = "a";
116
117 VERIFY(holds_alternative<string>(variant<int, string>("a")));
118 VERIFY(get<1>(v) == "a");
119 }
120
121 void dtor()
122 {
123 struct A {
124 A(int& called) : called(called) {}
125 ~A() {
126 called++;
127 }
128 int& called;
129 };
130 {
131 int called = 0;
132 { variant<string, A> a(in_place_index<1>, called); }
133 VERIFY(called == 1);
134 }
135 {
136 int called = 0;
137 { variant<string, A> a(in_place_index<0>); }
138 VERIFY(called == 0);
139 }
140 }
141
142 void in_place_index_ctor()
143 {
144 {
145 variant<int, string> v(in_place_index<1>, "a");
146 VERIFY(holds_alternative<string>(v));
147 VERIFY(get<1>(v) == "a");
148 }
149 {
150 variant<int, string> v(in_place_index<1>, {'a', 'b'});
151 VERIFY(holds_alternative<string>(v));
152 VERIFY(get<1>(v) == "ab");
153 }
154 }
155
156 void in_place_type_ctor()
157 {
158 {
159 variant<int, string> v(in_place_type<string>, "a");
160 VERIFY(holds_alternative<string>(v));
161 VERIFY(get<1>(v) == "a");
162 }
163 {
164 variant<int, string> v(in_place_type<string>, {'a', 'b'});
165 VERIFY(holds_alternative<string>(v));
166 VERIFY(get<1>(v) == "ab");
167 }
168 }
169
170 void emplace()
171 {
172 variant<int, string> v;
173 v.emplace<0>(1);
174 VERIFY(get<0>(v) == 1);
175 v.emplace<string>("a");
176 VERIFY(get<string>(v) == "a");
177 v.emplace<1>({'a', 'b'});
178 VERIFY(get<1>(v) == "ab");
179 v.emplace<string>({'a', 'c'});
180 VERIFY(get<string>(v) == "ac");
181 {
182 variant<int, AlwaysThrow> v;
183 AlwaysThrow a;
184 try { v.emplace<1>(a); } catch (nullptr_t) { }
185 VERIFY(v.valueless_by_exception());
186 }
187 {
188 variant<int, AlwaysThrow> v;
189 try { v.emplace<1>(AlwaysThrow{}); } catch (nullptr_t) { }
190 VERIFY(v.valueless_by_exception());
191 }
192 VERIFY(&v.emplace<0>(1) == &std::get<0>(v));
193 VERIFY(&v.emplace<int>(1) == &std::get<int>(v));
194 VERIFY(&v.emplace<1>("a") == &std::get<1>(v));
195 VERIFY(&v.emplace<string>("a") == &std::get<string>(v));
196 {
197 variant<vector<int>> v;
198 VERIFY(&v.emplace<0>({1,2,3}) == &std::get<0>(v));
199 VERIFY(&v.emplace<vector<int>>({1,2,3}) == &std::get<vector<int>>(v));
200 }
201 }
202
203 void test_get()
204 {
205 VERIFY(get<1>(variant<int, string>("a")) == "a");
206 VERIFY(get<string>(variant<int, string>("a")) == "a");
207 {
208 bool caught = false;
209
210 try
211 {
212 get<0>(variant<int, string>("a"));
213 }
214 catch (const bad_variant_access&)
215 {
216 caught = true;
217 }
218 VERIFY(caught);
219 }
220 {
221 bool caught = false;
222
223 try
224 {
225 get<int>(variant<int, string>("a"));
226 }
227 catch (const bad_variant_access&)
228 {
229 caught = true;
230 }
231 VERIFY(caught);
232 }
233 }
234
235 void test_relational()
236 {
237 VERIFY((variant<int, string>(2) < variant<int, string>(3)));
238 VERIFY((variant<int, string>(3) == variant<int, string>(3)));
239 VERIFY((variant<int, string>(3) > variant<int, string>(2)));
240 VERIFY((variant<int, string>(3) <= variant<int, string>(3)));
241 VERIFY((variant<int, string>(2) <= variant<int, string>(3)));
242 VERIFY((variant<int, string>(3) >= variant<int, string>(3)));
243 VERIFY((variant<int, string>(3) >= variant<int, string>(2)));
244 VERIFY((variant<int, string>(2) != variant<int, string>(3)));
245
246 VERIFY((variant<int, string>(2) < variant<int, string>("a")));
247 VERIFY((variant<string, int>(2) > variant<string, int>("a")));
248
249 {
250 variant<int, AlwaysThrow> v, w;
251 try
252 {
253 AlwaysThrow a;
254 v = a;
255 }
256 catch (nullptr_t) { }
257 VERIFY(v.valueless_by_exception());
258 VERIFY(v < w);
259 VERIFY(v <= w);
260 VERIFY(!(v == w));
261 VERIFY(v != w);
262 VERIFY(w > v);
263 VERIFY(w >= v);
264 }
265 }
266
267 void test_swap()
268 {
269 variant<int, string> a("a"), b("b");
270 a.swap(b);
271 VERIFY(get<1>(a) == "b");
272 VERIFY(get<1>(b) == "a");
273 swap(a, b);
274 VERIFY(get<1>(a) == "a");
275 VERIFY(get<1>(b) == "b");
276 }
277
278 void test_visit()
279 {
280 {
281 struct Visitor
282 {
283 int operator()(int, float) {
284 return 0;
285 }
286 int operator()(int, double) {
287 return 1;
288 }
289 int operator()(char, float) {
290 return 2;
291 }
292 int operator()(char, double) {
293 return 3;
294 }
295 int operator()(int, float) const {
296 return 5;
297 }
298 int operator()(int, double) const {
299 return 6;
300 }
301 int operator()(char, float) const {
302 return 7;
303 }
304 int operator()(char, double) const {
305 return 8;
306 }
307 } visitor1;
308 VERIFY(visit(visitor1, variant<int, char>(1), variant<float, double>(1.0f)) == 0);
309 VERIFY(visit(visitor1, variant<int, char>(1), variant<float, double>(1.0)) == 1);
310 VERIFY(visit(visitor1, variant<int, char>('a'), variant<float, double>(1.0f)) == 2);
311 VERIFY(visit(visitor1, variant<int, char>('a'), variant<float, double>(1.0)) == 3);
312
313 const auto& visitor2 = visitor1;
314 VERIFY(visit(visitor2, variant<int, char>(1), variant<float, double>(1.0f)) == 5);
315 VERIFY(visit(visitor2, variant<int, char>(1), variant<float, double>(1.0)) == 6);
316 VERIFY(visit(visitor2, variant<int, char>('a'), variant<float, double>(1.0f)) == 7);
317 VERIFY(visit(visitor2, variant<int, char>('a'), variant<float, double>(1.0)) == 8);
318 }
319
320 {
321 struct Visitor
322 {
323 int operator()(int, float) && {
324 return 0;
325 }
326 int operator()(int, double) && {
327 return 1;
328 }
329 int operator()(char, float) && {
330 return 2;
331 }
332 int operator()(char, double) && {
333 return 3;
334 }
335 };
336 VERIFY(visit(Visitor{}, variant<int, char>(1), variant<float, double>(1.0f)) == 0);
337 VERIFY(visit(Visitor{}, variant<int, char>(1), variant<float, double>(1.0)) == 1);
338 VERIFY(visit(Visitor{}, variant<int, char>('a'), variant<float, double>(1.0f)) == 2);
339 VERIFY(visit(Visitor{}, variant<int, char>('a'), variant<float, double>(1.0)) == 3);
340 }
341 }
342
343 void test_hash()
344 {
345 unordered_set<variant<int, string>> s;
346 VERIFY(s.emplace(3).second);
347 VERIFY(s.emplace("asdf").second);
348 VERIFY(s.emplace().second);
349 VERIFY(s.size() == 3);
350 VERIFY(!s.emplace(3).second);
351 VERIFY(!s.emplace("asdf").second);
352 VERIFY(!s.emplace().second);
353 VERIFY(s.size() == 3);
354 {
355 struct A
356 {
357 operator int()
358 {
359 throw nullptr;
360 }
361 };
362 variant<int, string> v;
363 try
364 {
365 v.emplace<0>(A{});
366 }
367 catch (nullptr_t)
368 {
369 }
370 VERIFY(v.valueless_by_exception());
371 VERIFY(s.insert(v).second);
372 VERIFY(s.size() == 4);
373 VERIFY(!s.insert(v).second);
374 }
375 }
376
377 void test_valueless_by_exception()
378 {
379 {
380 AlwaysThrow a;
381 bool caught = false;
382 try
383 {
384 variant<int, AlwaysThrow> v(a);
385 }
386 catch (nullptr_t)
387 {
388 caught = true;
389 }
390 VERIFY(caught);
391 }
392 {
393 AlwaysThrow a;
394 bool caught = false;
395 try
396 {
397 variant<int, AlwaysThrow> v(a);
398 }
399 catch (nullptr_t)
400 {
401 caught = true;
402 }
403 VERIFY(caught);
404 }
405 {
406 variant<int, AlwaysThrow> v;
407 bool caught = false;
408 try
409 {
410 AlwaysThrow a;
411 v = a;
412 }
413 catch (nullptr_t)
414 {
415 caught = true;
416 }
417 VERIFY(caught);
418 VERIFY(v.valueless_by_exception());
419 }
420 {
421 variant<int, AlwaysThrow> v;
422 bool caught = false;
423 try
424 {
425 v = AlwaysThrow{};
426 }
427 catch (nullptr_t)
428 {
429 caught = true;
430 }
431 VERIFY(caught);
432 VERIFY(v.valueless_by_exception());
433 }
434 }
435
436 int main()
437 {
438 default_ctor();
439 copy_ctor();
440 move_ctor();
441 arbitrary_ctor();
442 in_place_index_ctor();
443 in_place_type_ctor();
444 copy_assign();
445 move_assign();
446 arbitrary_assign();
447 dtor();
448 emplace();
449 test_get();
450 test_relational();
451 test_swap();
452 test_visit();
453 test_hash();
454 test_valueless_by_exception();
455 }