1
2// Copyright 2017 Peter Dimov.
3//
4// Distributed under the Boost Software License, Version 1.0.
5//
6// See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt
8
9#if defined(_MSC_VER)
10# pragma warning( disable: 4702 ) // unreachable code
11#endif
12
13#include <boost/variant2/variant.hpp>
14#include <boost/core/lightweight_test.hpp>
15#include <type_traits>
16#include <utility>
17#include <string>
18#include <stdexcept>
19
20using namespace boost::variant2;
21namespace v2d = boost::variant2::detail;
22
23#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
24
25//
26
27enum E1 { e1 };
28enum E1x { e1x };
29
30struct X1
31{
32 X1() = default;
33
34 X1( E1 ) noexcept {}
35 X1( E1x ) { throw std::runtime_error( "X1(E1x)" ); }
36};
37
38STATIC_ASSERT( std::is_nothrow_default_constructible<X1>::value );
39STATIC_ASSERT( std::is_nothrow_copy_constructible<X1>::value );
40STATIC_ASSERT( std::is_nothrow_move_constructible<X1>::value );
41STATIC_ASSERT( std::is_trivially_destructible<X1>::value );
42STATIC_ASSERT( v2d::is_trivially_move_assignable<X1>::value );
43STATIC_ASSERT( std::is_nothrow_constructible<X1, E1>::value );
44STATIC_ASSERT( !std::is_nothrow_constructible<X1, E1x>::value );
45
46enum E2 { e2 };
47enum E2x { e2x };
48
49struct X2
50{
51 X2();
52 ~X2();
53
54 X2( E2 ) noexcept {}
55 X2( E2x ) { throw std::runtime_error( "X2(E2x)" ); }
56};
57
58X2::X2() {}
59X2::~X2() {}
60
61STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value );
62STATIC_ASSERT( std::is_nothrow_copy_constructible<X2>::value );
63STATIC_ASSERT( std::is_nothrow_move_constructible<X2>::value );
64STATIC_ASSERT( !std::is_trivially_destructible<X2>::value );
65STATIC_ASSERT( std::is_nothrow_constructible<X2, E2>::value );
66STATIC_ASSERT( !std::is_nothrow_constructible<X2, E2x>::value );
67
68enum E3 { e3 };
69enum E3x { e3x };
70
71struct X3
72{
73 X3();
74
75 X3( X3 const& ) {}
76 X3( X3&& ) {}
77
78 X3( E3 ) noexcept {}
79 X3( E3x ) { throw std::runtime_error( "X3(E3x)" ); }
80
81 X3& operator=( X3 const& ) = default;
82 X3& operator=( X3&& ) = default;
83};
84
85X3::X3() {}
86
87STATIC_ASSERT( !std::is_nothrow_default_constructible<X3>::value );
88STATIC_ASSERT( !std::is_nothrow_copy_constructible<X3>::value );
89STATIC_ASSERT( !std::is_nothrow_move_constructible<X3>::value );
90STATIC_ASSERT( std::is_trivially_destructible<X3>::value );
91//STATIC_ASSERT( v2d::is_trivially_move_assignable<X3>::value );
92STATIC_ASSERT( std::is_nothrow_constructible<X3, E3>::value );
93STATIC_ASSERT( !std::is_nothrow_constructible<X3, E3x>::value );
94
95//
96
97STATIC_ASSERT( std::is_nothrow_default_constructible<monostate>::value );
98STATIC_ASSERT( std::is_nothrow_copy_constructible<monostate>::value );
99STATIC_ASSERT( std::is_nothrow_move_constructible<monostate>::value );
100STATIC_ASSERT( std::is_trivially_destructible<monostate>::value );
101
102//
103
104int main()
105{
106 {
107 variant<X2, X1> v;
108
109 BOOST_TEST_EQ( v.index(), 0 );
110
111 try
112 {
113 v = e1x;
114 BOOST_ERROR( "`v = e1x;` failed to throw" );
115 }
116 catch( std::exception const& )
117 {
118 // strong guarantee
119 BOOST_TEST_EQ( v.index(), 0 );
120 }
121 }
122
123 {
124 variant<X1, X2> v( e2 );
125
126 BOOST_TEST_EQ( v.index(), 1 );
127
128 try
129 {
130 v = e1x;
131 BOOST_ERROR( "`v = e1x;` failed to throw" );
132 }
133 catch( std::exception const& )
134 {
135 // strong guarantee
136 BOOST_TEST_EQ( v.index(), 1 );
137 }
138 }
139
140 {
141 variant<X2, X1, monostate> v;
142
143 BOOST_TEST_EQ( v.index(), 0 );
144
145 try
146 {
147 v = e1x;
148 BOOST_ERROR( "`v = e1x;` failed to throw" );
149 }
150 catch( std::exception const& )
151 {
152 // strong guarantee
153 BOOST_TEST_EQ( v.index(), 0 );
154 }
155 }
156
157 {
158 variant<X1, X2, monostate> v( e2 );
159
160 BOOST_TEST_EQ( v.index(), 1 );
161
162 try
163 {
164 v = e1x;
165 BOOST_ERROR( "`v = e1x;` failed to throw" );
166 }
167 catch( std::exception const& )
168 {
169 // strong guarantee
170 BOOST_TEST_EQ( v.index(), 1 );
171 }
172 }
173
174 {
175 variant<X2, X3, X1> v;
176
177 BOOST_TEST_EQ( v.index(), 0 );
178
179 try
180 {
181 v = e3x;
182 BOOST_ERROR( "`v = e3x;` failed to throw" );
183 }
184 catch( std::exception const& )
185 {
186 // strong guarantee
187 BOOST_TEST_EQ( v.index(), 0 );
188 }
189 }
190
191 {
192 variant<X2, X3, X1, monostate> v;
193
194 BOOST_TEST_EQ( v.index(), 0 );
195
196 try
197 {
198 v = e3x;
199 BOOST_ERROR( "`v = e3x;` failed to throw" );
200 }
201 catch( std::exception const& )
202 {
203 // strong guarantee
204 BOOST_TEST_EQ( v.index(), 0 );
205 }
206 }
207
208 {
209 variant<X2, X3> v;
210
211 BOOST_TEST_EQ( v.index(), 0 );
212
213 try
214 {
215 v = e3x;
216 BOOST_ERROR( "`v = e3x;` failed to throw" );
217 }
218 catch( std::exception const& )
219 {
220 // double buffered, no change
221 BOOST_TEST_EQ( v.index(), 0 );
222 }
223 }
224
225 {
226 variant<X3, X1> v;
227
228 BOOST_TEST_EQ( v.index(), 0 );
229
230 try
231 {
232 v = e1x;
233 BOOST_ERROR( "`v = e1x;` failed to throw" );
234 }
235 catch( std::exception const& )
236 {
237 // strong guarantee
238 BOOST_TEST_EQ( v.index(), 0 );
239 }
240 }
241
242 {
243 variant<X3, X1, monostate> v;
244
245 BOOST_TEST_EQ( v.index(), 0 );
246
247 try
248 {
249 v = e1x;
250 BOOST_ERROR( "`v = e1x;` failed to throw" );
251 }
252 catch( std::exception const& )
253 {
254 // strong guarantee
255 BOOST_TEST_EQ( v.index(), 0 );
256 }
257 }
258
259 return boost::report_errors();
260}
261

source code of boost/libs/variant2/test/variant_valueless.cpp