1 // { dg-options "-std=gnu++17" }
2 // { dg-do compile }
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
25 using namespace std;
26
27 struct AllDeleted
28 {
29 AllDeleted() = delete;
30 AllDeleted(const AllDeleted&) = delete;
31 AllDeleted(AllDeleted&&) = delete;
32 AllDeleted& operator=(const AllDeleted&) = delete;
33 AllDeleted& operator=(AllDeleted&&) = delete;
34 };
35
36 struct Empty
37 {
EmptyEmpty38 Empty() { };
EmptyEmpty39 Empty(const Empty&) { };
EmptyEmpty40 Empty(Empty&&) { };
operator =Empty41 Empty& operator=(const Empty&) { return *this; };
operator =Empty42 Empty& operator=(Empty&&) { return *this; };
43 };
44
45 struct DefaultNoexcept
46 {
47 DefaultNoexcept() noexcept = default;
48 DefaultNoexcept(const DefaultNoexcept&) noexcept = default;
49 DefaultNoexcept(DefaultNoexcept&&) noexcept = default;
50 DefaultNoexcept& operator=(const DefaultNoexcept&) noexcept = default;
51 DefaultNoexcept& operator=(DefaultNoexcept&&) noexcept = default;
52 };
53
54 struct MoveCtorOnly
55 {
56 MoveCtorOnly() noexcept = delete;
57 MoveCtorOnly(const MoveCtorOnly&) noexcept = delete;
MoveCtorOnlyMoveCtorOnly58 MoveCtorOnly(MoveCtorOnly&&) noexcept { }
59 MoveCtorOnly& operator=(const MoveCtorOnly&) noexcept = delete;
60 MoveCtorOnly& operator=(MoveCtorOnly&&) noexcept = delete;
61 };
62
63 struct MoveCtorAndSwapOnly : MoveCtorOnly { };
swap(MoveCtorAndSwapOnly &,MoveCtorAndSwapOnly &)64 void swap(MoveCtorAndSwapOnly&, MoveCtorAndSwapOnly&) { }
65
66 struct DeletedMoves
67 {
68 DeletedMoves() = default;
69 DeletedMoves(const DeletedMoves&) = default;
70 DeletedMoves(DeletedMoves&&) = delete;
71 DeletedMoves& operator=(const DeletedMoves&) = default;
72 DeletedMoves& operator=(DeletedMoves&&) = delete;
73 };
74
75 struct nonliteral
76 {
nonliteralnonliteral77 nonliteral() { }
78
79 bool operator<(const nonliteral&) const;
80 bool operator<=(const nonliteral&) const;
81 bool operator==(const nonliteral&) const;
82 bool operator!=(const nonliteral&) const;
83 bool operator>=(const nonliteral&) const;
84 bool operator>(const nonliteral&) const;
85 };
86
default_ctor()87 void default_ctor()
88 {
89 static_assert(is_default_constructible_v<variant<int, string>>);
90 static_assert(is_default_constructible_v<variant<string, string>>);
91 static_assert(!is_default_constructible_v<variant<AllDeleted, string>>);
92 static_assert(is_default_constructible_v<variant<string, AllDeleted>>);
93 static_assert(is_default_constructible_v<variant<DeletedMoves>>);
94
95 static_assert(noexcept(variant<int>()));
96 static_assert(!noexcept(variant<Empty>()));
97 static_assert(noexcept(variant<DefaultNoexcept>()));
98 }
99
copy_ctor()100 void copy_ctor()
101 {
102 static_assert(is_copy_constructible_v<variant<int, string>>);
103 static_assert(!is_copy_constructible_v<variant<AllDeleted, string>>);
104 static_assert(is_trivially_copy_constructible_v<variant<int>>);
105 static_assert(!is_trivially_copy_constructible_v<variant<std::string>>);
106 static_assert(is_trivially_copy_constructible_v<variant<DeletedMoves>>);
107
108 {
109 variant<int> a;
110 static_assert(noexcept(variant<int>(a)));
111 }
112 {
113 variant<string> a;
114 static_assert(!noexcept(variant<string>(a)));
115 }
116 {
117 variant<int, string> a;
118 static_assert(!noexcept(variant<int, string>(a)));
119 }
120 {
121 variant<int, char> a;
122 static_assert(noexcept(variant<int, char>(a)));
123 }
124 }
125
move_ctor()126 void move_ctor()
127 {
128 static_assert(is_move_constructible_v<variant<int, string>>);
129 static_assert(!is_move_constructible_v<variant<AllDeleted, string>>);
130 static_assert(is_move_constructible_v<variant<int, DeletedMoves>>); // uses copy ctor
131 static_assert(is_trivially_move_constructible_v<variant<int>>);
132 static_assert(!is_trivially_move_constructible_v<variant<std::string>>);
133 static_assert(!noexcept(variant<int, Empty>(declval<variant<int, Empty>>())));
134 static_assert(noexcept(variant<int, DefaultNoexcept>(declval<variant<int, DefaultNoexcept>>())));
135 }
136
arbitrary_ctor()137 void arbitrary_ctor()
138 {
139 static_assert(!is_constructible_v<variant<string, string>, const char*>);
140 static_assert(is_constructible_v<variant<int, string>, const char*>);
141 static_assert(noexcept(variant<int, Empty>(int{})));
142 static_assert(noexcept(variant<int, DefaultNoexcept>(int{})));
143 static_assert(!noexcept(variant<int, Empty>(Empty{})));
144 static_assert(noexcept(variant<int, DefaultNoexcept>(DefaultNoexcept{})));
145 }
146
147 struct none { none() = delete; };
anyany148 struct any { template <typename T> any(T&&) {} };
149
in_place_index_ctor()150 void in_place_index_ctor()
151 {
152 variant<string, string> a(in_place_index<0>, "a");
153 variant<string, string> b(in_place_index<1>, {'a'});
154
155 static_assert(!is_constructible_v<variant<none, any>, std::in_place_index_t<0>>, "PR libstdc++/90165");
156 }
157
in_place_type_ctor()158 void in_place_type_ctor()
159 {
160 variant<int, string, int> a(in_place_type<string>, "a");
161 variant<int, string, int> b(in_place_type<string>, {'a'});
162 static_assert(!is_constructible_v<variant<string, string>, in_place_type_t<string>, const char*>);
163 static_assert(!is_constructible_v<variant<none, any>, std::in_place_type_t<none>>, "PR libstdc++/90165");
164 }
165
dtor()166 void dtor()
167 {
168 static_assert(is_destructible_v<variant<int, string>>);
169 static_assert(is_destructible_v<variant<AllDeleted, string>>);
170 }
171
copy_assign()172 void copy_assign()
173 {
174 static_assert(is_copy_assignable_v<variant<int, string>>);
175 static_assert(!is_copy_assignable_v<variant<AllDeleted, string>>);
176 static_assert(is_trivially_copy_assignable_v<variant<int>>);
177 static_assert(!is_trivially_copy_assignable_v<variant<string>>);
178 static_assert(is_trivially_copy_assignable_v<variant<DeletedMoves>>);
179 {
180 variant<Empty> a;
181 static_assert(!noexcept(a = a));
182 }
183 {
184 variant<DefaultNoexcept> a;
185 static_assert(noexcept(a = a));
186 }
187 }
188
move_assign()189 void move_assign()
190 {
191 static_assert(is_move_assignable_v<variant<int, string>>);
192 static_assert(!is_move_assignable_v<variant<AllDeleted, string>>);
193 static_assert(is_move_assignable_v<variant<int, DeletedMoves>>); // uses copy assignment
194 static_assert(is_trivially_move_assignable_v<variant<int>>);
195 static_assert(!is_trivially_move_assignable_v<variant<string>>);
196 {
197 variant<Empty> a;
198 static_assert(!noexcept(a = std::move(a)));
199 }
200 {
201 variant<DefaultNoexcept> a;
202 static_assert(noexcept(a = std::move(a)));
203 }
204 }
205
arbitrary_assign()206 void arbitrary_assign()
207 {
208 static_assert(!is_assignable_v<variant<string, string>, const char*>);
209 static_assert(is_assignable_v<variant<int, string>, const char*>);
210 static_assert(noexcept(variant<int, Empty>() = int{}));
211 static_assert(noexcept(variant<int, DefaultNoexcept>() = int{}));
212 static_assert(!noexcept(variant<int, Empty>() = Empty{}));
213 static_assert(noexcept(variant<int, DefaultNoexcept>() = DefaultNoexcept{}));
214 }
215
test_get()216 void test_get()
217 {
218 static_assert(is_same<decltype(get<0>(variant<int, string>())), int&&>::value);
219 static_assert(is_same<decltype(get<1>(variant<int, string>())), string&&>::value);
220 static_assert(is_same<decltype(get<1>(variant<int, const string>())), const string&&>::value);
221
222 static_assert(is_same<decltype(get<int>(variant<int, string>())), int&&>::value);
223 static_assert(is_same<decltype(get<string>(variant<int, string>())), string&&>::value);
224 static_assert(is_same<decltype(get<const string>(variant<int, const string>())), const string&&>::value);
225 }
226
test_relational()227 void test_relational()
228 {
229 {
230 constexpr variant<int, nonliteral> a(42), b(43);
231 static_assert((a < b));
232 static_assert(!(a > b));
233 static_assert((a <= b));
234 static_assert(!(a == b));
235 static_assert((a != b));
236 static_assert(!(a >= b));
237 }
238 {
239 constexpr variant<int, nonliteral> a(42), b(42);
240 static_assert(!(a < b));
241 static_assert(!(a > b));
242 static_assert((a <= b));
243 static_assert((a == b));
244 static_assert(!(a != b));
245 static_assert((a >= b));
246 }
247 {
248 constexpr variant<int, nonliteral> a(43), b(42);
249 static_assert(!(a < b));
250 static_assert((a > b));
251 static_assert(!(a <= b));
252 static_assert(!(a == b));
253 static_assert((a != b));
254 static_assert((a >= b));
255 }
256 {
257 constexpr monostate a, b;
258 static_assert(!(a < b));
259 static_assert(!(a > b));
260 static_assert((a <= b));
261 static_assert((a == b));
262 static_assert(!(a != b));
263 static_assert((a >= b));
264 }
265 }
266
267 // Not swappable, and variant<C> not swappable via the generic std::swap.
268 struct C { };
269 void swap(C&, C&) = delete;
270
271 static_assert( !std::is_swappable_v<variant<C>> );
272 static_assert( !std::is_swappable_v<variant<int, C>> );
273 static_assert( !std::is_swappable_v<variant<C, int>> );
274
275 // Not swappable, and variant<D> not swappable via the generic std::swap.
276 struct D { D(D&&) = delete; };
277
278 static_assert( !std::is_swappable_v<variant<D>> );
279 static_assert( !std::is_swappable_v<variant<int, D>> );
280 static_assert( !std::is_swappable_v<variant<D, int>> );
281
test_swap()282 void test_swap()
283 {
284 static_assert(is_swappable_v<variant<int, string>>);
285 static_assert(!is_swappable_v<variant<MoveCtorOnly>>);
286 static_assert(is_swappable_v<variant<MoveCtorAndSwapOnly>>);
287 static_assert(!is_swappable_v<variant<AllDeleted>>);
288 }
289
test_visit()290 void test_visit()
291 {
292 {
293 struct Visitor
294 {
295 void operator()(monostate) {}
296 void operator()(const int&) {}
297 };
298 struct CVisitor
299 {
300 void operator()(monostate) const {}
301 void operator()(const int&) const {}
302 };
303 }
304 {
305 struct Visitor
306 {
307 bool operator()(int, float) { return false; }
308 bool operator()(int, double) { return false; }
309 bool operator()(char, float) { return false; }
310 bool operator()(char, double) { return false; }
311 };
312 visit(Visitor(), variant<int, char>(), variant<float, double>());
313 }
314 {
315 struct Visitor
316 {
317 constexpr bool operator()(const int&) { return true; }
318 constexpr bool operator()(const nonliteral&) { return false; }
319 };
320 static_assert(visit(Visitor(), variant<int, nonliteral>(0)));
321 }
322 {
323 struct Visitor
324 {
325 constexpr bool operator()(const int&) { return true; }
326 constexpr bool operator()(const nonliteral&) { return false; }
327 };
328 static_assert(visit(Visitor(), variant<int, nonliteral>(0)));
329 }
330 // PR libstdc++/79513
331 {
332 std::variant<int> v [[gnu::unused]] (5);
333 std::visit([](int&){}, v);
334 std::visit([](int&&){}, std::move(v));
335 }
336 }
337
test_constexpr()338 void test_constexpr()
339 {
340 constexpr variant<int> a;
341 static_assert(holds_alternative<int>(a));
342 constexpr variant<int, char> b(in_place_index<0>, int{});
343 static_assert(holds_alternative<int>(b));
344 constexpr variant<int, char> c(in_place_type<int>, int{});
345 static_assert(holds_alternative<int>(c));
346 constexpr variant<int, char> d(in_place_index<1>, char{});
347 static_assert(holds_alternative<char>(d));
348 constexpr variant<int, char> e(in_place_type<char>, char{});
349 static_assert(holds_alternative<char>(e));
350 constexpr variant<int, char> f(char{});
351 static_assert(holds_alternative<char>(f));
352
353 {
354 struct literal {
355 constexpr literal() = default;
356 };
357
358 constexpr variant<literal, nonliteral> v{};
359 constexpr variant<literal, nonliteral> v1{in_place_type<literal>};
360 constexpr variant<literal, nonliteral> v2{in_place_index<0>};
361 }
362
363 {
364 constexpr variant<int> a(42);
365 static_assert(get<0>(a) == 42);
366 }
367 {
368 constexpr variant<int, nonliteral> a(42);
369 static_assert(get<0>(a) == 42);
370 }
371 {
372 constexpr variant<nonliteral, int> a(42);
373 static_assert(get<1>(a) == 42);
374 }
375 {
376 constexpr variant<int> a(42);
377 static_assert(get<int>(a) == 42);
378 }
379 {
380 constexpr variant<int, nonliteral> a(42);
381 static_assert(get<int>(a) == 42);
382 }
383 {
384 constexpr variant<nonliteral, int> a(42);
385 static_assert(get<int>(a) == 42);
386 }
387 {
388 constexpr variant<int> a(42);
389 static_assert(get<0>(std::move(a)) == 42);
390 }
391 {
392 constexpr variant<int, nonliteral> a(42);
393 static_assert(get<0>(std::move(a)) == 42);
394 }
395 {
396 constexpr variant<nonliteral, int> a(42);
397 static_assert(get<1>(std::move(a)) == 42);
398 }
399 {
400 constexpr variant<int> a(42);
401 static_assert(get<int>(std::move(a)) == 42);
402 }
403 {
404 constexpr variant<int, nonliteral> a(42);
405 static_assert(get<int>(std::move(a)) == 42);
406 }
407 {
408 constexpr variant<nonliteral, int> a(42);
409 static_assert(get<int>(std::move(a)) == 42);
410 }
411 }
412
test_pr77641()413 void test_pr77641()
414 {
415 struct X {
416 constexpr X() { }
417 };
418
419 constexpr std::variant<X> v1 = X{};
420 }
421
422 namespace adl_trap
423 {
424 struct X {
425 X() = default;
Xadl_trap::X426 X(int) { }
Xadl_trap::X427 X(std::initializer_list<int>, const X&) { }
428 };
move(T &)429 template<typename T> void move(T&) { }
forward(T &)430 template<typename T> void forward(T&) { }
431
432 struct Visitor {
operator ()adl_trap::Visitor433 template<typename T> void operator()(T&&) { }
434 };
435 }
436
test_adl()437 void test_adl()
438 {
439 using adl_trap::X;
440 X x;
441 std::initializer_list<int> il;
442 adl_trap::Visitor vis;
443
444 std::variant<X> v0(x);
445 v0 = x;
446 v0.emplace<0>(x);
447 v0.emplace<0>(il, x);
448 visit(vis, v0);
449 variant<X> v1{in_place_index<0>, x};
450 variant<X> v2{in_place_type<X>, x};
451 variant<X> v3{in_place_index<0>, il, x};
452 variant<X> v4{in_place_type<X>, il, x};
453 }
454
test_variant_alternative()455 void test_variant_alternative()
456 {
457 static_assert(is_same_v<variant_alternative_t<0, variant<int, string>>, int>);
458 static_assert(is_same_v<variant_alternative_t<1, variant<int, string>>, string>);
459
460 static_assert(is_same_v<variant_alternative_t<0, const variant<int>>, const int>);
461 static_assert(is_same_v<variant_alternative_t<0, volatile variant<int>>, volatile int>);
462 static_assert(is_same_v<variant_alternative_t<0, const volatile variant<int>>, const volatile int>);
463 }
464
465 template<typename V, typename T>
has_type_emplace(int)466 constexpr auto has_type_emplace(int) -> decltype((declval<V>().template emplace<T>(), true))
467 { return true; };
468
469 template<typename V, typename T>
has_type_emplace(...)470 constexpr bool has_type_emplace(...)
471 { return false; };
472
473 template<typename V, size_t N>
has_index_emplace(int)474 constexpr auto has_index_emplace(int) -> decltype((declval<V>().template emplace<N>(), true))
475 { return true; };
476
477 template<typename V, size_t T>
has_index_emplace(...)478 constexpr bool has_index_emplace(...)
479 { return false; };
480
test_emplace()481 void test_emplace()
482 {
483 static_assert(has_type_emplace<variant<int>, int>(0));
484 static_assert(!has_type_emplace<variant<long>, int>(0));
485 static_assert(has_index_emplace<variant<int>, 0>(0));
486 static_assert(!has_type_emplace<variant<AllDeleted>, AllDeleted>(0));
487 static_assert(!has_index_emplace<variant<AllDeleted>, 0>(0));
488 static_assert(has_type_emplace<variant<int, AllDeleted>, int>(0));
489 static_assert(has_index_emplace<variant<int, AllDeleted>, 0>(0));
490 static_assert(has_type_emplace<variant<int, vector<int>, AllDeleted>, vector<int>>(0));
491 static_assert(has_index_emplace<variant<int, vector<int>, AllDeleted>, 1>(0));
492
493 // The above tests only check the emplace members are available for
494 // overload resolution. The following odr-uses will instantiate them:
495 variant<int, vector<int>, AllDeleted> v;
496 v.emplace<0>(1);
497 v.emplace<int>(1);
498 v.emplace<1>(1, 1);
499 v.emplace<vector<int>>(1, 1);
500 v.emplace<1>({1, 2, 3, 4});
501 v.emplace<vector<int>>({1, 2, 3, 4});
502 }
503
test_triviality()504 void test_triviality()
505 {
506 #define TEST_TEMPLATE(DT, CC, MC, CA, MA, CC_VAL, MC_VAL, CA_VAL, MA_VAL) \
507 { \
508 struct A \
509 { \
510 ~A() DT; \
511 A(const A&) CC; \
512 A(A&&) MC; \
513 A& operator=(const A&) CA; \
514 A& operator=(A&&) MA; \
515 }; \
516 static_assert(CC_VAL == is_trivially_copy_constructible_v<variant<A>>); \
517 static_assert(MC_VAL == is_trivially_move_constructible_v<variant<A>>); \
518 static_assert(CA_VAL == is_trivially_copy_assignable_v<variant<A>>); \
519 static_assert(MA_VAL == is_trivially_move_assignable_v<variant<A>>); \
520 }
521 TEST_TEMPLATE(=default, =default, =default, =default, =default, true, true, true, true)
522 TEST_TEMPLATE(=default, =default, =default, =default, , true, true, true, false)
523 TEST_TEMPLATE(=default, =default, =default, , =default, true, true, false, true)
524 TEST_TEMPLATE(=default, =default, =default, , , true, true, false, false)
525 TEST_TEMPLATE(=default, =default, , =default, =default, true, false, true, false)
526 TEST_TEMPLATE(=default, =default, , =default, , true, false, true, false)
527 TEST_TEMPLATE(=default, =default, , , =default, true, false, false, false)
528 TEST_TEMPLATE(=default, =default, , , , true, false, false, false)
529 TEST_TEMPLATE(=default, , =default, =default, =default, false, true, false, true)
530 TEST_TEMPLATE(=default, , =default, =default, , false, true, false, false)
531 TEST_TEMPLATE(=default, , =default, , =default, false, true, false, true)
532 TEST_TEMPLATE(=default, , =default, , , false, true, false, false)
533 TEST_TEMPLATE(=default, , , =default, =default, false, false, false, false)
534 TEST_TEMPLATE(=default, , , =default, , false, false, false, false)
535 TEST_TEMPLATE(=default, , , , =default, false, false, false, false)
536 TEST_TEMPLATE(=default, , , , , false, false, false, false)
537 TEST_TEMPLATE( , =default, =default, =default, =default, false, false, false, false)
538 TEST_TEMPLATE( , =default, =default, =default, , false, false, false, false)
539 TEST_TEMPLATE( , =default, =default, , =default, false, false, false, false)
540 TEST_TEMPLATE( , =default, =default, , , false, false, false, false)
541 TEST_TEMPLATE( , =default, , =default, =default, false, false, false, false)
542 TEST_TEMPLATE( , =default, , =default, , false, false, false, false)
543 TEST_TEMPLATE( , =default, , , =default, false, false, false, false)
544 TEST_TEMPLATE( , =default, , , , false, false, false, false)
545 TEST_TEMPLATE( , , =default, =default, =default, false, false, false, false)
546 TEST_TEMPLATE( , , =default, =default, , false, false, false, false)
547 TEST_TEMPLATE( , , =default, , =default, false, false, false, false)
548 TEST_TEMPLATE( , , =default, , , false, false, false, false)
549 TEST_TEMPLATE( , , , =default, =default, false, false, false, false)
550 TEST_TEMPLATE( , , , =default, , false, false, false, false)
551 TEST_TEMPLATE( , , , , =default, false, false, false, false)
552 TEST_TEMPLATE( , , , , , false, false, false, false)
553 #undef TEST_TEMPLATE
554
555 #define TEST_TEMPLATE(CC, MC, CA, MA) \
556 { \
557 struct A \
558 { \
559 A(const A&) CC; \
560 A(A&&) MC; \
561 A& operator=(const A&) CA; \
562 A& operator=(A&&) MA; \
563 }; \
564 static_assert(!is_trivially_copy_constructible_v<variant<AllDeleted, A>>); \
565 static_assert(!is_trivially_move_constructible_v<variant<AllDeleted, A>>); \
566 static_assert(!is_trivially_copy_assignable_v<variant<AllDeleted, A>>); \
567 static_assert(!is_trivially_move_assignable_v<variant<AllDeleted, A>>); \
568 }
569 TEST_TEMPLATE(=default, =default, =default, =default)
570 TEST_TEMPLATE(=default, =default, =default, )
571 TEST_TEMPLATE(=default, =default, , =default)
572 TEST_TEMPLATE(=default, =default, , )
573 TEST_TEMPLATE(=default, , =default, =default)
574 TEST_TEMPLATE(=default, , =default, )
575 TEST_TEMPLATE(=default, , , =default)
576 TEST_TEMPLATE(=default, , , )
577 TEST_TEMPLATE( , =default, =default, =default)
578 TEST_TEMPLATE( , =default, =default, )
579 TEST_TEMPLATE( , =default, , =default)
580 TEST_TEMPLATE( , =default, , )
581 TEST_TEMPLATE( , , =default, =default)
582 TEST_TEMPLATE( , , =default, )
583 TEST_TEMPLATE( , , , =default)
584 TEST_TEMPLATE( , , , )
585 #undef TEST_TEMPLATE
586
587 static_assert(is_trivially_copy_constructible_v<variant<DefaultNoexcept, int, char, float, double>>);
588 static_assert(is_trivially_move_constructible_v<variant<DefaultNoexcept, int, char, float, double>>);
589 static_assert(is_trivially_copy_assignable_v<variant<DefaultNoexcept, int, char, float, double>>);
590 static_assert(is_trivially_move_assignable_v<variant<DefaultNoexcept, int, char, float, double>>);
591 }
592