]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/variant/exception_safety.cc
1 // Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
18 // { dg-do run { target c++17 } }
23 #include <memory_resource>
28 #include <testsuite_hooks.h>
33 #if _GLIBCXX_USE_CXX11_ABI
34 std::variant
<int, std::pmr::string
, std::pmr::vector
<int>> v(1);
35 VERIFY( v
.index() == 0 );
39 std::pmr::string s
= "how long is a piece of SSO string?";
40 v
.emplace
<1>(s
, std::pmr::null_memory_resource());
43 catch(const std::bad_alloc
&)
45 VERIFY( v
.valueless_by_exception() );
49 VERIFY( v
.index() == 0 );
53 v
.emplace
<2>({1, 2, 3}, std::pmr::null_memory_resource());
56 catch(const std::bad_alloc
&)
58 VERIFY( v
.valueless_by_exception() );
68 X(int i
) : i(1) { if (i
> 2) throw 3; }
69 X(std::initializer_list
<int> l
) : i(2) { if (l
.size() > 2) throw 3; }
72 static_assert( std::is_trivially_copyable_v
<X
> );
74 std::variant
<std::monostate
, int, X
> v(111);
75 VERIFY( v
.index() == 1 );
84 VERIFY( !v
.valueless_by_exception() );
85 VERIFY( v
.index() == 1 );
86 VERIFY( std::get
<int>(v
) == 111 );
90 VERIFY( v
.index() == 2 );
91 VERIFY( std::get
<X
>(v
).i
== 1 );
100 VERIFY( !v
.valueless_by_exception() );
101 VERIFY( v
.index() == 2 );
102 VERIFY( std::get
<X
>(v
).i
== 1 );
107 v
.emplace
<X
>({1, 2, 3});
112 VERIFY( !v
.valueless_by_exception() );
113 VERIFY( v
.index() == 2 );
114 VERIFY( std::get
<X
>(v
).i
== 1 );
118 template<typename T
, typename V
>
119 bool bad_emplace(V
& v
)
122 operator T() const { throw 1; }
125 const auto index
= v
.index();
129 if (std::is_same_v
<T
, std::any
>)
131 // Need to test std::any differently, because emplace<std::any>(X{})
132 // would create a std::any with a contained X, instead of using
133 // X::operator any() to convert to std::any.
136 ThrowOnCopy(const ThrowOnCopy
&) { throw 1; }
138 v
.template emplace
<std::any
>(t
);
141 v
.template emplace
<T
>(X
{});
145 return v
.index() == index
;
153 struct TriviallyCopyable
{ int i
= 0; };
155 std::variant
<std::monostate
, int, TriviallyCopyable
, std::optional
<int>,
156 std::string
, std::vector
<int>, std::function
<void()>, std::any
,
157 std::shared_ptr
<int>, std::weak_ptr
<int>, std::unique_ptr
<int>> v(1);
158 VERIFY( v
.index() == 1 );
160 VERIFY( bad_emplace
<int>(v
) );
161 VERIFY( bad_emplace
<TriviallyCopyable
>(v
) );
162 VERIFY( bad_emplace
<std::optional
<int>>(v
) );
163 VERIFY( bad_emplace
<std::string
>(v
) );
164 VERIFY( bad_emplace
<std::vector
<int>>(v
) );
165 VERIFY( bad_emplace
<std::function
<void()>>(v
) );
166 VERIFY( bad_emplace
<std::any
>(v
) );
167 VERIFY( bad_emplace
<std::shared_ptr
<int>>(v
) );
168 VERIFY( bad_emplace
<std::weak_ptr
<int>>(v
) );
169 VERIFY( bad_emplace
<std::unique_ptr
<int>>(v
) );
175 // LWG 2904. Make variant move-assignment more exception safe
180 ThrowOnCopy(const ThrowOnCopy
&) { throw 1; }
181 ThrowOnCopy
& operator=(const ThrowOnCopy
&) { throw "shouldn't happen"; }
182 ThrowOnCopy(ThrowOnCopy
&&) noexcept
{ }
185 std::variant
<int, ThrowOnCopy
> v1(std::in_place_type
<ThrowOnCopy
>), v2(2);
188 v2
= v1
; // uses variant<Types...>::operator=(const variant&)
193 VERIFY( !v2
.valueless_by_exception() );
194 VERIFY( v2
.index() == 0 );
195 VERIFY( std::get
<0>(v2
) == 2 );
201 v2
= toc
; // uses variant<Types...>::operator=(T&&)
206 VERIFY( !v2
.valueless_by_exception() );
207 VERIFY( v2
.index() == 0 );
208 VERIFY( std::get
<0>(v2
) == 2 );