]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/variant/exception_safety.cc
1 // Copyright (C) 2019-2021 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-options "-std=gnu++17" }
19 // { dg-do run { target c++17 } }
24 #include <memory_resource>
29 #include <testsuite_hooks.h>
34 #if _GLIBCXX_USE_CXX11_ABI
35 std::variant
<int, std::pmr::string
, std::pmr::vector
<int>> v(1);
36 VERIFY( v
.index() == 0 );
40 std::pmr::string s
= "how long is a piece of SSO string?";
41 v
.emplace
<1>(s
, std::pmr::null_memory_resource());
44 catch(const std::bad_alloc
&)
46 VERIFY( v
.valueless_by_exception() );
50 VERIFY( v
.index() == 0 );
54 v
.emplace
<2>({1, 2, 3}, std::pmr::null_memory_resource());
57 catch(const std::bad_alloc
&)
59 VERIFY( v
.valueless_by_exception() );
69 X(int i
) : i(1) { if (i
> 2) throw 3; }
70 X(std::initializer_list
<int> l
) : i(2) { if (l
.size() > 2) throw 3; }
73 static_assert( std::is_trivially_copyable_v
<X
> );
75 std::variant
<std::monostate
, int, X
> v(111);
76 VERIFY( v
.index() == 1 );
85 VERIFY( !v
.valueless_by_exception() );
86 VERIFY( v
.index() == 1 );
87 VERIFY( std::get
<int>(v
) == 111 );
91 VERIFY( v
.index() == 2 );
92 VERIFY( std::get
<X
>(v
).i
== 1 );
101 VERIFY( !v
.valueless_by_exception() );
102 VERIFY( v
.index() == 2 );
103 VERIFY( std::get
<X
>(v
).i
== 1 );
108 v
.emplace
<X
>({1, 2, 3});
113 VERIFY( !v
.valueless_by_exception() );
114 VERIFY( v
.index() == 2 );
115 VERIFY( std::get
<X
>(v
).i
== 1 );
119 template<typename T
, typename V
>
120 bool bad_emplace(V
& v
)
123 operator T() const { throw 1; }
126 const auto index
= v
.index();
130 if (std::is_same_v
<T
, std::any
>)
132 // Need to test std::any differently, because emplace<std::any>(X{})
133 // would create a std::any with a contained X, instead of using
134 // X::operator any() to convert to std::any.
137 ThrowOnCopy(const ThrowOnCopy
&) { throw 1; }
139 v
.template emplace
<std::any
>(t
);
142 v
.template emplace
<T
>(X
{});
146 return v
.index() == index
;
154 struct TriviallyCopyable
{ int i
= 0; };
156 std::variant
<std::monostate
, int, TriviallyCopyable
, std::optional
<int>,
157 std::string
, std::vector
<int>, std::function
<void()>, std::any
,
158 std::shared_ptr
<int>, std::weak_ptr
<int>, std::unique_ptr
<int>> v(1);
159 VERIFY( v
.index() == 1 );
161 VERIFY( bad_emplace
<int>(v
) );
162 VERIFY( bad_emplace
<TriviallyCopyable
>(v
) );
163 VERIFY( bad_emplace
<std::optional
<int>>(v
) );
164 VERIFY( bad_emplace
<std::string
>(v
) );
165 VERIFY( bad_emplace
<std::vector
<int>>(v
) );
166 VERIFY( bad_emplace
<std::function
<void()>>(v
) );
167 VERIFY( bad_emplace
<std::any
>(v
) );
168 VERIFY( bad_emplace
<std::shared_ptr
<int>>(v
) );
169 VERIFY( bad_emplace
<std::weak_ptr
<int>>(v
) );
170 VERIFY( bad_emplace
<std::unique_ptr
<int>>(v
) );
176 // LWG 2904. Make variant move-assignment more exception safe
181 ThrowOnCopy(const ThrowOnCopy
&) { throw 1; }
182 ThrowOnCopy
& operator=(const ThrowOnCopy
&) { throw "shouldn't happen"; }
183 ThrowOnCopy(ThrowOnCopy
&&) noexcept
{ }
186 std::variant
<int, ThrowOnCopy
> v1(std::in_place_type
<ThrowOnCopy
>), v2(2);
189 v2
= v1
; // uses variant<Types...>::operator=(const variant&)
194 VERIFY( !v2
.valueless_by_exception() );
195 VERIFY( v2
.index() == 0 );
196 VERIFY( std::get
<0>(v2
) == 2 );
202 v2
= toc
; // uses variant<Types...>::operator=(T&&)
207 VERIFY( !v2
.valueless_by_exception() );
208 VERIFY( v2
.index() == 0 );
209 VERIFY( std::get
<0>(v2
) == 2 );