1 // { dg-options "-std=gnu++17" }
2 // { dg-do run { target c++17 } }
4 // Copyright (C) 2016-2021 Free Software Foundation, Inc.
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)
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.
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/>.
24 #include <unordered_set>
25 #include <ext/throw_allocator.h>
26 #include <testsuite_hooks.h>
32 AlwaysThrow() = default;
34 AlwaysThrow(const AlwaysThrow
&)
37 AlwaysThrow(AlwaysThrow
&&)
40 AlwaysThrow
& operator=(const AlwaysThrow
&)
46 AlwaysThrow
& operator=(AlwaysThrow
&&)
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); }
62 DeletedMoves() = default;
63 DeletedMoves(const DeletedMoves
&) = default;
64 DeletedMoves(DeletedMoves
&&) = delete;
65 DeletedMoves
& operator=(const DeletedMoves
&) = default;
66 DeletedMoves
& operator=(DeletedMoves
&&) = delete;
71 variant
<monostate
, string
> v
;
72 VERIFY(holds_alternative
<monostate
>(v
));
77 variant
<monostate
, string
> v("a");
78 VERIFY(holds_alternative
<string
>(v
));
79 variant
<monostate
, string
> u(v
);
80 VERIFY(holds_alternative
<string
>(u
));
81 VERIFY(get
<string
>(u
) == "a");
86 variant
<monostate
, string
> v("a");
87 VERIFY(holds_alternative
<string
>(v
));
88 variant
<monostate
, string
> u(std::move(v
));
89 VERIFY(holds_alternative
<string
>(u
));
90 VERIFY(get
<string
>(u
) == "a");
91 VERIFY(holds_alternative
<string
>(v
));
93 variant
<vector
<int>, DeletedMoves
> d
{std::in_place_index
<0>, {1, 2, 3, 4}};
94 // DeletedMoves is not move constructible, so this uses copy ctor:
95 variant
<vector
<int>, DeletedMoves
> e(std::move(d
));
96 VERIFY(std::get
<0>(d
).size() == 4);
97 VERIFY(std::get
<0>(e
).size() == 4);
100 void arbitrary_ctor()
102 variant
<int, string
> v("a");
103 VERIFY(holds_alternative
<string
>(v
));
104 VERIFY(get
<1>(v
) == "a");
108 variant
<string
, bool> x
= "abc";
109 VERIFY(x
.index() == 0);
115 U(char16_t c
) : c(c
) { }
118 variant
<char, U
> x
= u
'\u2043';
119 VERIFY(x
.index() == 1);
120 VERIFY(std::get
<1>(x
).c
== u
'\u2043');
123 Double(double& d
) : d(d
) { }
127 variant
<int, Double
> y
= d
;
128 VERIFY(y
.index() == 1);
129 VERIFY(std::get
<1>(y
).d
== d
);
134 variant
<float, int> v1
= 'a';
135 VERIFY(std::get
<1>(v1
) == int('a'));
136 variant
<float, long> v2
= 0;
137 VERIFY(std::get
<1>(v2
) == 0L);
138 struct big_int
{ big_int(int) { } };
139 variant
<float, big_int
> v3
= 0;
140 VERIFY(v3
.index() == 1);
144 // P1957R2 Converting from T* to bool should be considered narrowing
145 struct ConvertibleToBool
147 operator bool() const { return true; }
149 variant
<bool> v1
= ConvertibleToBool();
150 VERIFY(std::get
<0>(v1
) == true);
151 variant
<bool, int> v2
= ConvertibleToBool();
152 VERIFY(std::get
<0>(v2
) == true);
153 variant
<int, bool> v3
= ConvertibleToBool();
154 VERIFY(std::get
<1>(v3
) == true);
158 struct ThrowingMoveCtorThrowsCopyCtor
160 ThrowingMoveCtorThrowsCopyCtor() noexcept
= default;
161 ThrowingMoveCtorThrowsCopyCtor(ThrowingMoveCtorThrowsCopyCtor
&&) {}
162 ThrowingMoveCtorThrowsCopyCtor(ThrowingMoveCtorThrowsCopyCtor
const&)
167 ThrowingMoveCtorThrowsCopyCtor
& operator=(ThrowingMoveCtorThrowsCopyCtor
&&) noexcept
169 ThrowingMoveCtorThrowsCopyCtor
& operator=(ThrowingMoveCtorThrowsCopyCtor
const&) noexcept
175 variant
<monostate
, string
> v("a");
176 VERIFY(holds_alternative
<string
>(v
));
177 variant
<monostate
, string
> u
;
179 VERIFY(holds_alternative
<string
>(u
));
180 VERIFY(get
<string
>(u
) == "a");
182 std::variant
<int, ThrowingMoveCtorThrowsCopyCtor
> v1
,
183 v2
= ThrowingMoveCtorThrowsCopyCtor();
184 bool should_throw
= false;
193 VERIFY(should_throw
);
199 variant
<monostate
, string
> v("a");
200 VERIFY(holds_alternative
<string
>(v
));
201 variant
<monostate
, string
> u
;
203 VERIFY(holds_alternative
<string
>(u
));
204 VERIFY(get
<string
>(u
) == "a");
205 VERIFY(holds_alternative
<string
>(v
));
207 variant
<vector
<int>, DeletedMoves
> d
{std::in_place_index
<0>, {1, 2, 3, 4}};
208 variant
<vector
<int>, DeletedMoves
> e
;
209 // DeletedMoves is not move assignable, so this uses copy assignment:
211 VERIFY(std::get
<0>(d
).size() == 4);
212 VERIFY(std::get
<0>(e
).size() == 4);
215 void arbitrary_assign()
217 variant
<int, string
> v
;
220 VERIFY(holds_alternative
<string
>(variant
<int, string
>("a")));
221 VERIFY(get
<1>(v
) == "a");
225 using T1
= variant
<float, int>;
228 VERIFY(v1
.index() == 1);
230 using T2
= variant
<float, long>;
233 VERIFY(v2
.index() == 1);
238 using T3
= variant
<float, big_int
>;
241 VERIFY(v3
.index() == 1);
245 // P1957R2 Converting from T* to bool should be considered narrowing
246 struct ConvertibleToBool
248 operator bool() const { return true; }
251 v1
= ConvertibleToBool();
252 VERIFY(std::get
<0>(v1
) == true);
253 variant
<bool, int> v2
;
254 v2
= ConvertibleToBool();
255 VERIFY(std::get
<0>(v2
) == true);
256 variant
<int, bool> v3
;
257 v3
= ConvertibleToBool();
258 VERIFY(std::get
<1>(v3
) == true);
265 A(int& called
) : called(called
) {}
273 { variant
<string
, A
> a(in_place_index
<1>, called
); }
278 { variant
<string
, A
> a(in_place_index
<0>); }
283 void in_place_index_ctor()
286 variant
<int, string
> v(in_place_index
<1>, "a");
287 VERIFY(holds_alternative
<string
>(v
));
288 VERIFY(get
<1>(v
) == "a");
291 variant
<int, string
> v(in_place_index
<1>, {'a', 'b'});
292 VERIFY(holds_alternative
<string
>(v
));
293 VERIFY(get
<1>(v
) == "ab");
297 void in_place_type_ctor()
300 variant
<int, string
> v(in_place_type
<string
>, "a");
301 VERIFY(holds_alternative
<string
>(v
));
302 VERIFY(get
<1>(v
) == "a");
305 variant
<int, string
> v(in_place_type
<string
>, {'a', 'b'});
306 VERIFY(holds_alternative
<string
>(v
));
307 VERIFY(get
<1>(v
) == "ab");
313 variant
<int, string
> v
;
315 VERIFY(get
<0>(v
) == 1);
316 v
.emplace
<string
>("a");
317 VERIFY(get
<string
>(v
) == "a");
318 v
.emplace
<1>({'a', 'b'});
319 VERIFY(get
<1>(v
) == "ab");
320 v
.emplace
<string
>({'a', 'c'});
321 VERIFY(get
<string
>(v
) == "ac");
323 variant
<int, AlwaysThrow
> v
;
325 try { v
.emplace
<1>(a
); } catch (nullptr_t
) { }
326 VERIFY(v
.valueless_by_exception());
328 VERIFY(!v
.valueless_by_exception());
331 variant
<int, AlwaysThrow
> v
;
332 try { v
.emplace
<1>(AlwaysThrow
{}); } catch (nullptr_t
) { }
333 VERIFY(v
.valueless_by_exception());
335 VERIFY(!v
.valueless_by_exception());
337 VERIFY(&v
.emplace
<0>(1) == &std::get
<0>(v
));
338 VERIFY(&v
.emplace
<int>(1) == &std::get
<int>(v
));
339 VERIFY(&v
.emplace
<1>("a") == &std::get
<1>(v
));
340 VERIFY(&v
.emplace
<string
>("a") == &std::get
<string
>(v
));
342 variant
<vector
<int>> v
;
343 VERIFY(&v
.emplace
<0>({1,2,3}) == &std::get
<0>(v
));
344 VERIFY(&v
.emplace
<vector
<int>>({1,2,3}) == &std::get
<vector
<int>>(v
));
348 // Ensure no copies of the vector are made, only moves.
349 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c21
351 // static_assert(__detail::__variant::_Never_valueless_alt<vector<AlwaysThrow>>::value);
352 variant
<int, DeletedMoves
, vector
<AlwaysThrow
>> v
;
354 v
.emplace
<vector
<AlwaysThrow
>>(1);
357 // To test the emplace(initializer_list<U>, Args&&...) members we
358 // can't use AlwaysThrow because elements in an initialier_list
359 // are always copied. Use throw_allocator instead.
360 using Vector
= vector
<int, __gnu_cxx::throw_allocator_limit
<int>>;
361 // static_assert(__detail::__variant::_Never_valueless_alt<Vector>::value);
362 variant
<int, DeletedMoves
, Vector
> vv
;
363 Vector::allocator_type::set_limit(1);
365 Vector::allocator_type::set_limit(1);
366 vv
.emplace
<Vector
>(1, 1);
367 Vector::allocator_type::set_limit(1);
369 Vector::allocator_type::set_limit(1);
370 vv
.emplace
<2>({1, 2, 3});
371 Vector::allocator_type::set_limit(1);
372 vv
.emplace
<Vector
>({1, 2, 3, 4});
374 Vector::allocator_type::set_limit(0);
377 } catch (const __gnu_cxx::forced_error
&) {
379 VERIFY(vv
.valueless_by_exception());
385 VERIFY(get
<1>(variant
<int, string
>("a")) == "a");
386 VERIFY(get
<string
>(variant
<int, string
>("a")) == "a");
392 get
<0>(variant
<int, string
>("a"));
394 catch (const bad_variant_access
&)
405 get
<int>(variant
<int, string
>("a"));
407 catch (const bad_variant_access
&)
415 void test_relational()
417 VERIFY((variant
<int, string
>(2) < variant
<int, string
>(3)));
418 VERIFY((variant
<int, string
>(3) == variant
<int, string
>(3)));
419 VERIFY((variant
<int, string
>(3) > variant
<int, string
>(2)));
420 VERIFY((variant
<int, string
>(3) <= variant
<int, string
>(3)));
421 VERIFY((variant
<int, string
>(2) <= variant
<int, string
>(3)));
422 VERIFY((variant
<int, string
>(3) >= variant
<int, string
>(3)));
423 VERIFY((variant
<int, string
>(3) >= variant
<int, string
>(2)));
424 VERIFY((variant
<int, string
>(2) != variant
<int, string
>(3)));
426 VERIFY((variant
<int, string
>(2) < variant
<int, string
>("a")));
427 VERIFY((variant
<string
, int>(2) > variant
<string
, int>("a")));
430 variant
<int, AlwaysThrow
> v
, w
;
436 catch (nullptr_t
) { }
437 VERIFY(v
.valueless_by_exception());
450 variant
<int, string
> a("a"), b("b");
452 VERIFY(get
<1>(a
) == "b");
453 VERIFY(get
<1>(b
) == "a");
455 VERIFY(get
<1>(a
) == "a");
456 VERIFY(get
<1>(b
) == "b");
464 int operator()(int, float) {
467 int operator()(int, double) {
470 int operator()(char, float) {
473 int operator()(char, double) {
476 int operator()(int, float) const {
479 int operator()(int, double) const {
482 int operator()(char, float) const {
485 int operator()(char, double) const {
489 VERIFY(visit(visitor1
, variant
<int, char>(1), variant
<float, double>(1.0f
)) == 0);
490 VERIFY(visit(visitor1
, variant
<int, char>(1), variant
<float, double>(1.0)) == 1);
491 VERIFY(visit(visitor1
, variant
<int, char>('a'), variant
<float, double>(1.0f
)) == 2);
492 VERIFY(visit(visitor1
, variant
<int, char>('a'), variant
<float, double>(1.0)) == 3);
494 const auto& visitor2
= visitor1
;
495 VERIFY(visit(visitor2
, variant
<int, char>(1), variant
<float, double>(1.0f
)) == 5);
496 VERIFY(visit(visitor2
, variant
<int, char>(1), variant
<float, double>(1.0)) == 6);
497 VERIFY(visit(visitor2
, variant
<int, char>('a'), variant
<float, double>(1.0f
)) == 7);
498 VERIFY(visit(visitor2
, variant
<int, char>('a'), variant
<float, double>(1.0)) == 8);
504 int operator()(int, float) && {
507 int operator()(int, double) && {
510 int operator()(char, float) && {
513 int operator()(char, double) && {
517 VERIFY(visit(Visitor
{}, variant
<int, char>(1), variant
<float, double>(1.0f
)) == 0);
518 VERIFY(visit(Visitor
{}, variant
<int, char>(1), variant
<float, double>(1.0)) == 1);
519 VERIFY(visit(Visitor
{}, variant
<int, char>('a'), variant
<float, double>(1.0f
)) == 2);
520 VERIFY(visit(Visitor
{}, variant
<int, char>('a'), variant
<float, double>(1.0)) == 3);
526 Hashable(const char* s
) : s(s
) { }
527 // Non-trivial special member functions:
528 Hashable(const Hashable
&) { }
529 Hashable(Hashable
&&) noexcept
{ }
534 bool operator==(const Hashable
& rhs
) const noexcept
535 { return s
== rhs
.s
; }
539 template<> struct hash
<Hashable
> {
540 size_t operator()(const Hashable
& h
) const noexcept
541 { return hash
<std::string
>()(h
.s
); }
547 unordered_set
<variant
<int, Hashable
>> s
;
548 VERIFY(s
.emplace(3).second
);
549 VERIFY(s
.emplace("asdf").second
);
550 VERIFY(s
.emplace().second
);
551 VERIFY(s
.size() == 3);
552 VERIFY(!s
.emplace(3).second
);
553 VERIFY(!s
.emplace("asdf").second
);
554 VERIFY(!s
.emplace().second
);
555 VERIFY(s
.size() == 3);
564 variant
<int, Hashable
> v
;
572 VERIFY(v
.valueless_by_exception());
573 VERIFY(s
.insert(v
).second
);
574 VERIFY(s
.size() == 4);
575 VERIFY(!s
.insert(v
).second
);
579 void test_valueless_by_exception()
586 variant
<int, AlwaysThrow
> v(a
);
599 variant
<int, AlwaysThrow
> v(a
);
608 variant
<int, AlwaysThrow
> v
;
620 VERIFY(v
.valueless_by_exception());
623 variant
<int, AlwaysThrow
> v
;
634 VERIFY(v
.valueless_by_exception());
644 in_place_index_ctor();
645 in_place_type_ctor();
656 test_valueless_by_exception();