variant_valueless.cpp 5.7 KB

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