1 // { dg-do run { target c++17 } }
3 // Copyright (C) 2016-2024 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING3. If not see
18 // <http://www.gnu.org/licenses/>.
23 #include <unordered_set>
24 #include <ext/throw_allocator.h>
25 #include <testsuite_hooks.h>
31 AlwaysThrow() = default;
33 AlwaysThrow(const AlwaysThrow
&)
36 AlwaysThrow(AlwaysThrow
&&)
39 AlwaysThrow
& operator=(const AlwaysThrow
&)
45 AlwaysThrow
& operator=(AlwaysThrow
&&)
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); }
61 DeletedMoves() = default;
62 DeletedMoves(const DeletedMoves
&) = default;
63 DeletedMoves(DeletedMoves
&&) = delete;
64 DeletedMoves
& operator=(const DeletedMoves
&) = default;
65 DeletedMoves
& operator=(DeletedMoves
&&) = delete;
70 variant
<monostate
, string
> v
;
71 VERIFY(holds_alternative
<monostate
>(v
));
76 variant
<monostate
, string
> v("a");
77 VERIFY(holds_alternative
<string
>(v
));
78 variant
<monostate
, string
> u(v
);
79 VERIFY(holds_alternative
<string
>(u
));
80 VERIFY(get
<string
>(u
) == "a");
85 variant
<monostate
, string
> v("a");
86 VERIFY(holds_alternative
<string
>(v
));
87 variant
<monostate
, string
> u(std::move(v
));
88 VERIFY(holds_alternative
<string
>(u
));
89 VERIFY(get
<string
>(u
) == "a");
90 VERIFY(holds_alternative
<string
>(v
));
92 variant
<vector
<int>, DeletedMoves
> d
{std::in_place_index
<0>, {1, 2, 3, 4}};
93 // DeletedMoves is not move constructible, so this uses copy ctor:
94 variant
<vector
<int>, DeletedMoves
> e(std::move(d
));
95 VERIFY(std::get
<0>(d
).size() == 4);
96 VERIFY(std::get
<0>(e
).size() == 4);
101 variant
<int, string
> v("a");
102 VERIFY(holds_alternative
<string
>(v
));
103 VERIFY(get
<1>(v
) == "a");
107 variant
<string
, bool> x
= "abc";
108 VERIFY(x
.index() == 0);
114 U(char16_t c
) : c(c
) { }
117 variant
<char, U
> x
= u
'\u2043';
118 VERIFY(x
.index() == 1);
119 VERIFY(std::get
<1>(x
).c
== u
'\u2043');
122 Double(double& d
) : d(d
) { }
126 variant
<int, Double
> y
= d
;
127 VERIFY(y
.index() == 1);
128 VERIFY(std::get
<1>(y
).d
== d
);
133 variant
<float, int> v1
= 'a';
134 VERIFY(std::get
<1>(v1
) == int('a'));
135 variant
<float, long> v2
= 0;
136 VERIFY(std::get
<1>(v2
) == 0L);
137 struct big_int
{ big_int(int) { } };
138 variant
<float, big_int
> v3
= 0;
139 VERIFY(v3
.index() == 1);
143 // P1957R2 Converting from T* to bool should be considered narrowing
144 struct ConvertibleToBool
146 operator bool() const { return true; }
148 variant
<bool> v1
= ConvertibleToBool();
149 VERIFY(std::get
<0>(v1
) == true);
150 variant
<bool, int> v2
= ConvertibleToBool();
151 VERIFY(std::get
<0>(v2
) == true);
152 variant
<int, bool> v3
= ConvertibleToBool();
153 VERIFY(std::get
<1>(v3
) == true);
157 struct ThrowingMoveCtorThrowsCopyCtor
159 ThrowingMoveCtorThrowsCopyCtor() noexcept
= default;
160 ThrowingMoveCtorThrowsCopyCtor(ThrowingMoveCtorThrowsCopyCtor
&&) {}
161 ThrowingMoveCtorThrowsCopyCtor(ThrowingMoveCtorThrowsCopyCtor
const&)
166 ThrowingMoveCtorThrowsCopyCtor
& operator=(ThrowingMoveCtorThrowsCopyCtor
&&) noexcept
168 ThrowingMoveCtorThrowsCopyCtor
& operator=(ThrowingMoveCtorThrowsCopyCtor
const&) noexcept
174 variant
<monostate
, string
> v("a");
175 VERIFY(holds_alternative
<string
>(v
));
176 variant
<monostate
, string
> u
;
178 VERIFY(holds_alternative
<string
>(u
));
179 VERIFY(get
<string
>(u
) == "a");
181 std::variant
<int, ThrowingMoveCtorThrowsCopyCtor
> v1
,
182 v2
= ThrowingMoveCtorThrowsCopyCtor();
183 bool should_throw
= false;
192 VERIFY(should_throw
);
198 variant
<monostate
, string
> v("a");
199 VERIFY(holds_alternative
<string
>(v
));
200 variant
<monostate
, string
> u
;
202 VERIFY(holds_alternative
<string
>(u
));
203 VERIFY(get
<string
>(u
) == "a");
204 VERIFY(holds_alternative
<string
>(v
));
206 variant
<vector
<int>, DeletedMoves
> d
{std::in_place_index
<0>, {1, 2, 3, 4}};
207 variant
<vector
<int>, DeletedMoves
> e
;
208 // DeletedMoves is not move assignable, so this uses copy assignment:
210 VERIFY(std::get
<0>(d
).size() == 4);
211 VERIFY(std::get
<0>(e
).size() == 4);
214 void arbitrary_assign()
216 variant
<int, string
> v
;
219 VERIFY(holds_alternative
<string
>(variant
<int, string
>("a")));
220 VERIFY(get
<1>(v
) == "a");
224 using T1
= variant
<float, int>;
227 VERIFY(v1
.index() == 1);
229 using T2
= variant
<float, long>;
232 VERIFY(v2
.index() == 1);
237 using T3
= variant
<float, big_int
>;
240 VERIFY(v3
.index() == 1);
244 // P1957R2 Converting from T* to bool should be considered narrowing
245 struct ConvertibleToBool
247 operator bool() const { return true; }
250 v1
= ConvertibleToBool();
251 VERIFY(std::get
<0>(v1
) == true);
252 variant
<bool, int> v2
;
253 v2
= ConvertibleToBool();
254 VERIFY(std::get
<0>(v2
) == true);
255 variant
<int, bool> v3
;
256 v3
= ConvertibleToBool();
257 VERIFY(std::get
<1>(v3
) == true);
264 A(int& called
) : called(called
) {}
272 { variant
<string
, A
> a(in_place_index
<1>, called
); }
277 { variant
<string
, A
> a(in_place_index
<0>); }
282 void in_place_index_ctor()
285 variant
<int, string
> v(in_place_index
<1>, "a");
286 VERIFY(holds_alternative
<string
>(v
));
287 VERIFY(get
<1>(v
) == "a");
290 variant
<int, string
> v(in_place_index
<1>, {'a', 'b'});
291 VERIFY(holds_alternative
<string
>(v
));
292 VERIFY(get
<1>(v
) == "ab");
296 void in_place_type_ctor()
299 variant
<int, string
> v(in_place_type
<string
>, "a");
300 VERIFY(holds_alternative
<string
>(v
));
301 VERIFY(get
<1>(v
) == "a");
304 variant
<int, string
> v(in_place_type
<string
>, {'a', 'b'});
305 VERIFY(holds_alternative
<string
>(v
));
306 VERIFY(get
<1>(v
) == "ab");
312 variant
<int, string
> v
;
314 VERIFY(get
<0>(v
) == 1);
315 v
.emplace
<string
>("a");
316 VERIFY(get
<string
>(v
) == "a");
317 v
.emplace
<1>({'a', 'b'});
318 VERIFY(get
<1>(v
) == "ab");
319 v
.emplace
<string
>({'a', 'c'});
320 VERIFY(get
<string
>(v
) == "ac");
322 variant
<int, AlwaysThrow
> v
;
324 try { v
.emplace
<1>(a
); } catch (nullptr_t
) { }
325 VERIFY(v
.valueless_by_exception());
327 VERIFY(!v
.valueless_by_exception());
330 variant
<int, AlwaysThrow
> v
;
331 try { v
.emplace
<1>(AlwaysThrow
{}); } catch (nullptr_t
) { }
332 VERIFY(v
.valueless_by_exception());
334 VERIFY(!v
.valueless_by_exception());
336 VERIFY(&v
.emplace
<0>(1) == &std::get
<0>(v
));
337 VERIFY(&v
.emplace
<int>(1) == &std::get
<int>(v
));
338 VERIFY(&v
.emplace
<1>("a") == &std::get
<1>(v
));
339 VERIFY(&v
.emplace
<string
>("a") == &std::get
<string
>(v
));
341 variant
<vector
<int>> v
;
342 VERIFY(&v
.emplace
<0>({1,2,3}) == &std::get
<0>(v
));
343 VERIFY(&v
.emplace
<vector
<int>>({1,2,3}) == &std::get
<vector
<int>>(v
));
347 // Ensure no copies of the vector are made, only moves.
348 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c21
350 // static_assert(__detail::__variant::_Never_valueless_alt<vector<AlwaysThrow>>::value);
351 variant
<int, DeletedMoves
, vector
<AlwaysThrow
>> v
;
353 v
.emplace
<vector
<AlwaysThrow
>>(1);
356 // To test the emplace(initializer_list<U>, Args&&...) members we
357 // can't use AlwaysThrow because elements in an initialier_list
358 // are always copied. Use throw_allocator instead.
359 using Vector
= vector
<int, __gnu_cxx::throw_allocator_limit
<int>>;
360 // static_assert(__detail::__variant::_Never_valueless_alt<Vector>::value);
361 variant
<int, DeletedMoves
, Vector
> vv
;
362 Vector::allocator_type::set_limit(1);
364 Vector::allocator_type::set_limit(1);
365 vv
.emplace
<Vector
>(1, 1);
366 Vector::allocator_type::set_limit(1);
368 Vector::allocator_type::set_limit(1);
369 vv
.emplace
<2>({1, 2, 3});
370 Vector::allocator_type::set_limit(1);
371 vv
.emplace
<Vector
>({1, 2, 3, 4});
373 Vector::allocator_type::set_limit(0);
376 } catch (const __gnu_cxx::forced_error
&) {
378 VERIFY(vv
.valueless_by_exception());
384 VERIFY(get
<1>(variant
<int, string
>("a")) == "a");
385 VERIFY(get
<string
>(variant
<int, string
>("a")) == "a");
391 get
<0>(variant
<int, string
>("a"));
393 catch (const bad_variant_access
&)
404 get
<int>(variant
<int, string
>("a"));
406 catch (const bad_variant_access
&)
414 void test_relational()
416 VERIFY((variant
<int, string
>(2) < variant
<int, string
>(3)));
417 VERIFY((variant
<int, string
>(3) == variant
<int, string
>(3)));
418 VERIFY((variant
<int, string
>(3) > variant
<int, string
>(2)));
419 VERIFY((variant
<int, string
>(3) <= variant
<int, string
>(3)));
420 VERIFY((variant
<int, string
>(2) <= variant
<int, string
>(3)));
421 VERIFY((variant
<int, string
>(3) >= variant
<int, string
>(3)));
422 VERIFY((variant
<int, string
>(3) >= variant
<int, string
>(2)));
423 VERIFY((variant
<int, string
>(2) != variant
<int, string
>(3)));
425 VERIFY((variant
<int, string
>(2) < variant
<int, string
>("a")));
426 VERIFY((variant
<string
, int>(2) > variant
<string
, int>("a")));
429 variant
<int, AlwaysThrow
> v
, w
;
435 catch (nullptr_t
) { }
436 VERIFY(v
.valueless_by_exception());
449 variant
<int, string
> a("a"), b("b");
451 VERIFY(get
<1>(a
) == "b");
452 VERIFY(get
<1>(b
) == "a");
454 VERIFY(get
<1>(a
) == "a");
455 VERIFY(get
<1>(b
) == "b");
463 int operator()(int, float) {
466 int operator()(int, double) {
469 int operator()(char, float) {
472 int operator()(char, double) {
475 int operator()(int, float) const {
478 int operator()(int, double) const {
481 int operator()(char, float) const {
484 int operator()(char, double) const {
488 VERIFY(visit(visitor1
, variant
<int, char>(1), variant
<float, double>(1.0f
)) == 0);
489 VERIFY(visit(visitor1
, variant
<int, char>(1), variant
<float, double>(1.0)) == 1);
490 VERIFY(visit(visitor1
, variant
<int, char>('a'), variant
<float, double>(1.0f
)) == 2);
491 VERIFY(visit(visitor1
, variant
<int, char>('a'), variant
<float, double>(1.0)) == 3);
493 const auto& visitor2
= visitor1
;
494 VERIFY(visit(visitor2
, variant
<int, char>(1), variant
<float, double>(1.0f
)) == 5);
495 VERIFY(visit(visitor2
, variant
<int, char>(1), variant
<float, double>(1.0)) == 6);
496 VERIFY(visit(visitor2
, variant
<int, char>('a'), variant
<float, double>(1.0f
)) == 7);
497 VERIFY(visit(visitor2
, variant
<int, char>('a'), variant
<float, double>(1.0)) == 8);
503 int operator()(int, float) && {
506 int operator()(int, double) && {
509 int operator()(char, float) && {
512 int operator()(char, double) && {
516 VERIFY(visit(Visitor
{}, variant
<int, char>(1), variant
<float, double>(1.0f
)) == 0);
517 VERIFY(visit(Visitor
{}, variant
<int, char>(1), variant
<float, double>(1.0)) == 1);
518 VERIFY(visit(Visitor
{}, variant
<int, char>('a'), variant
<float, double>(1.0f
)) == 2);
519 VERIFY(visit(Visitor
{}, variant
<int, char>('a'), variant
<float, double>(1.0)) == 3);
525 Hashable(const char* s
) : s(s
) { }
526 // Non-trivial special member functions:
527 Hashable(const Hashable
&) { }
528 Hashable(Hashable
&&) noexcept
{ }
533 bool operator==(const Hashable
& rhs
) const noexcept
534 { return s
== rhs
.s
; }
538 template<> struct hash
<Hashable
> {
539 size_t operator()(const Hashable
& h
) const noexcept
540 { return hash
<std::string
>()(h
.s
); }
546 unordered_set
<variant
<int, Hashable
>> s
;
547 VERIFY(s
.emplace(3).second
);
548 VERIFY(s
.emplace("asdf").second
);
549 VERIFY(s
.emplace().second
);
550 VERIFY(s
.size() == 3);
551 VERIFY(!s
.emplace(3).second
);
552 VERIFY(!s
.emplace("asdf").second
);
553 VERIFY(!s
.emplace().second
);
554 VERIFY(s
.size() == 3);
563 variant
<int, Hashable
> v
;
571 VERIFY(v
.valueless_by_exception());
572 VERIFY(s
.insert(v
).second
);
573 VERIFY(s
.size() == 4);
574 VERIFY(!s
.insert(v
).second
);
578 void test_valueless_by_exception()
585 variant
<int, AlwaysThrow
> v(a
);
598 variant
<int, AlwaysThrow
> v(a
);
607 variant
<int, AlwaysThrow
> v
;
619 VERIFY(v
.valueless_by_exception());
622 variant
<int, AlwaysThrow
> v
;
633 VERIFY(v
.valueless_by_exception());
643 in_place_index_ctor();
644 in_place_type_ctor();
655 test_valueless_by_exception();