• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 using namespace boost::variant2;
21 namespace v2d = boost::variant2::detail;
22 
23 #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
24 
25 //
26 
27 enum E1 { e1 };
28 enum E1x { e1x };
29 
30 struct X1
31 {
32     X1() = default;
33 
X1X134     X1( E1 ) noexcept {}
X1X135     X1( E1x ) { throw std::runtime_error( "X1(E1x)" ); }
36 };
37 
38 STATIC_ASSERT( std::is_nothrow_default_constructible<X1>::value );
39 STATIC_ASSERT( std::is_nothrow_copy_constructible<X1>::value );
40 STATIC_ASSERT( std::is_nothrow_move_constructible<X1>::value );
41 STATIC_ASSERT( std::is_trivially_destructible<X1>::value );
42 STATIC_ASSERT( v2d::is_trivially_move_assignable<X1>::value );
43 STATIC_ASSERT( std::is_nothrow_constructible<X1, E1>::value );
44 STATIC_ASSERT( !std::is_nothrow_constructible<X1, E1x>::value );
45 
46 enum E2 { e2 };
47 enum E2x { e2x };
48 
49 struct X2
50 {
51     X2();
52     ~X2();
53 
X2X254     X2( E2 ) noexcept {}
X2X255     X2( E2x ) { throw std::runtime_error( "X2(E2x)" ); }
56 };
57 
X2()58 X2::X2() {}
~X2()59 X2::~X2() {}
60 
61 STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value );
62 STATIC_ASSERT( std::is_nothrow_copy_constructible<X2>::value );
63 STATIC_ASSERT( std::is_nothrow_move_constructible<X2>::value );
64 STATIC_ASSERT( !std::is_trivially_destructible<X2>::value );
65 STATIC_ASSERT( std::is_nothrow_constructible<X2, E2>::value );
66 STATIC_ASSERT( !std::is_nothrow_constructible<X2, E2x>::value );
67 
68 enum E3 { e3 };
69 enum E3x { e3x };
70 
71 struct X3
72 {
73     X3();
74 
X3X375     X3( X3 const& ) {}
X3X376     X3( X3&& ) {}
77 
X3X378     X3( E3 ) noexcept {}
X3X379     X3( E3x ) { throw std::runtime_error( "X3(E3x)" ); }
80 
81     X3& operator=( X3 const& ) = default;
82     X3& operator=( X3&& ) = default;
83 };
84 
X3()85 X3::X3() {}
86 
87 STATIC_ASSERT( !std::is_nothrow_default_constructible<X3>::value );
88 STATIC_ASSERT( !std::is_nothrow_copy_constructible<X3>::value );
89 STATIC_ASSERT( !std::is_nothrow_move_constructible<X3>::value );
90 STATIC_ASSERT( std::is_trivially_destructible<X3>::value );
91 //STATIC_ASSERT( v2d::is_trivially_move_assignable<X3>::value );
92 STATIC_ASSERT( std::is_nothrow_constructible<X3, E3>::value );
93 STATIC_ASSERT( !std::is_nothrow_constructible<X3, E3x>::value );
94 
95 //
96 
97 STATIC_ASSERT( std::is_nothrow_default_constructible<monostate>::value );
98 STATIC_ASSERT( std::is_nothrow_copy_constructible<monostate>::value );
99 STATIC_ASSERT( std::is_nothrow_move_constructible<monostate>::value );
100 STATIC_ASSERT( std::is_trivially_destructible<monostate>::value );
101 
102 //
103 
main()104 int 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