variant_get_test.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. //-----------------------------------------------------------------------------
  2. // boost-libs variant/test/variant_get_test.cpp source file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2014-2019 Antony Polukhin
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See
  9. // accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #ifdef _MSC_VER
  12. #pragma warning(disable: 4127) // conditional expression is constant
  13. #pragma warning(disable: 4181) // qualifier applied to reference type; ignored
  14. #endif
  15. #include "boost/variant/get.hpp"
  16. #include "boost/variant/variant.hpp"
  17. #include "boost/variant/polymorphic_get.hpp"
  18. #include "boost/variant/recursive_wrapper.hpp"
  19. #include "boost/core/lightweight_test.hpp"
  20. struct base {
  21. int trash;
  22. base() : trash(123) {}
  23. base(const base& b) : trash(b.trash) { int i = 100; (void)i; }
  24. const base& operator=(const base& b) {
  25. trash = b.trash;
  26. int i = 100; (void)i;
  27. return *this;
  28. }
  29. virtual ~base(){}
  30. };
  31. struct derived1 : base{};
  32. struct derived2 : base{};
  33. struct vbase { short trash; virtual ~vbase(){} virtual int foo() const { return 0; } };
  34. struct vderived1 : virtual vbase{ virtual int foo() const { return 1; } };
  35. struct vderived2 : virtual vbase{ virtual int foo() const { return 3; } };
  36. struct vderived3 : vderived1, vderived2 { virtual int foo() const { return 3; } };
  37. typedef boost::variant<int, base, derived1, derived2, std::string> var_t;
  38. typedef boost::variant<int, derived1, derived2, std::string> var_t_shortened;
  39. typedef boost::variant<base, derived1, derived2> var_t_no_fallback;
  40. typedef boost::variant<int&, base&, derived1&, derived2&, std::string&> var_ref_t;
  41. typedef boost::variant<const int&, const base&, const derived1&, const derived2&, const std::string&> var_cref_t;
  42. struct recursive_structure;
  43. typedef boost::variant<
  44. int, base, derived1, derived2, std::string, boost::recursive_wrapper<recursive_structure>
  45. > var_req_t;
  46. struct recursive_structure { var_req_t var; };
  47. template <class TypeInVariant, class V, class TestType>
  48. inline void check_polymorphic_get_on_types_impl_single_type(V* v)
  49. {
  50. typedef typename boost::add_reference<TestType>::type ref_test_t;
  51. typedef typename boost::add_reference<const TestType>::type cref_test_t;
  52. const bool exact_same = !!boost::is_same<TypeInVariant, TestType>::value;
  53. const bool ref_same = !!boost::is_same<TypeInVariant, ref_test_t>::value;
  54. if (exact_same || ref_same) {
  55. BOOST_TEST(boost::polymorphic_get<TestType>(v));
  56. BOOST_TEST(boost::polymorphic_get<const TestType>(v));
  57. BOOST_TEST(boost::polymorphic_strict_get<TestType>(v));
  58. BOOST_TEST(boost::polymorphic_strict_get<const TestType>(v));
  59. BOOST_TEST(boost::polymorphic_relaxed_get<TestType>(v));
  60. BOOST_TEST(boost::polymorphic_relaxed_get<const TestType>(v));
  61. BOOST_TEST(boost::polymorphic_get<cref_test_t>(v));
  62. BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v));
  63. BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v));
  64. if (ref_same) {
  65. BOOST_TEST(boost::polymorphic_get<ref_test_t>(v));
  66. BOOST_TEST(boost::polymorphic_get<cref_test_t>(v));
  67. BOOST_TEST(boost::polymorphic_strict_get<ref_test_t>(v));
  68. BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v));
  69. BOOST_TEST(boost::polymorphic_relaxed_get<ref_test_t>(v));
  70. BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v));
  71. }
  72. } else {
  73. BOOST_TEST(!boost::polymorphic_get<TestType>(v));
  74. BOOST_TEST(!boost::polymorphic_get<const TestType>(v));
  75. BOOST_TEST(!boost::polymorphic_strict_get<TestType>(v));
  76. BOOST_TEST(!boost::polymorphic_strict_get<const TestType>(v));
  77. BOOST_TEST(!boost::polymorphic_relaxed_get<TestType>(v));
  78. BOOST_TEST(!boost::polymorphic_relaxed_get<const TestType>(v));
  79. }
  80. }
  81. template <class T, class V, class TestType>
  82. inline void check_get_on_types_impl_single_type(V* v)
  83. {
  84. typedef typename boost::add_reference<TestType>::type ref_test_t;
  85. typedef typename boost::add_reference<const TestType>::type cref_test_t;
  86. const bool exact_same = !!boost::is_same<T, TestType>::value;
  87. const bool ref_same = !!boost::is_same<T, ref_test_t>::value;
  88. if (exact_same || ref_same) {
  89. BOOST_TEST(boost::get<TestType>(v));
  90. BOOST_TEST(boost::get<const TestType>(v));
  91. BOOST_TEST(boost::strict_get<TestType>(v));
  92. BOOST_TEST(boost::strict_get<const TestType>(v));
  93. BOOST_TEST(boost::relaxed_get<TestType>(v));
  94. BOOST_TEST(boost::relaxed_get<const TestType>(v));
  95. BOOST_TEST(boost::get<cref_test_t>(v));
  96. BOOST_TEST(boost::strict_get<cref_test_t>(v));
  97. BOOST_TEST(boost::relaxed_get<cref_test_t>(v));
  98. if (ref_same) {
  99. BOOST_TEST(boost::get<ref_test_t>(v));
  100. BOOST_TEST(boost::get<cref_test_t>(v));
  101. BOOST_TEST(boost::strict_get<ref_test_t>(v));
  102. BOOST_TEST(boost::strict_get<cref_test_t>(v));
  103. BOOST_TEST(boost::relaxed_get<ref_test_t>(v));
  104. BOOST_TEST(boost::relaxed_get<cref_test_t>(v));
  105. }
  106. } else {
  107. BOOST_TEST(!boost::get<TestType>(v));
  108. BOOST_TEST(!boost::get<const TestType>(v));
  109. BOOST_TEST(!boost::strict_get<TestType>(v));
  110. BOOST_TEST(!boost::strict_get<const TestType>(v));
  111. BOOST_TEST(!boost::relaxed_get<TestType>(v));
  112. BOOST_TEST(!boost::relaxed_get<const TestType>(v));
  113. }
  114. }
  115. template <class T, class V>
  116. inline void check_get_on_types_impl(V* v)
  117. {
  118. check_get_on_types_impl_single_type<T, V, int>(v);
  119. check_polymorphic_get_on_types_impl_single_type<T, V, int>(v);
  120. check_get_on_types_impl_single_type<T, V, base>(v);
  121. check_get_on_types_impl_single_type<T, V, derived1>(v);
  122. check_polymorphic_get_on_types_impl_single_type<T, V, derived1>(v);
  123. check_get_on_types_impl_single_type<T, V, derived2>(v);
  124. check_polymorphic_get_on_types_impl_single_type<T, V, derived2>(v);
  125. check_get_on_types_impl_single_type<T, V, std::string>(v);
  126. check_polymorphic_get_on_types_impl_single_type<T, V, std::string>(v);
  127. // Never exist in here
  128. BOOST_TEST(!boost::relaxed_get<short>(v));
  129. BOOST_TEST(!boost::relaxed_get<const short>(v));
  130. BOOST_TEST(!boost::relaxed_get<char>(v));
  131. BOOST_TEST(!boost::relaxed_get<char*>(v));
  132. BOOST_TEST(!boost::relaxed_get<bool>(v));
  133. BOOST_TEST(!boost::relaxed_get<const bool>(v));
  134. BOOST_TEST(!boost::polymorphic_relaxed_get<short>(v));
  135. BOOST_TEST(!boost::polymorphic_relaxed_get<const short>(v));
  136. BOOST_TEST(!boost::polymorphic_relaxed_get<char>(v));
  137. BOOST_TEST(!boost::polymorphic_relaxed_get<char*>(v));
  138. BOOST_TEST(!boost::polymorphic_relaxed_get<bool>(v));
  139. BOOST_TEST(!boost::polymorphic_relaxed_get<const bool>(v));
  140. boost::get<T>(*v); // Must compile
  141. boost::get<const T>(*v); // Must compile
  142. boost::strict_get<T>(*v); // Must compile
  143. boost::strict_get<const T>(*v); // Must compile
  144. bool is_ref = boost::is_lvalue_reference<T>::value;
  145. (void)is_ref;
  146. if (!is_ref) {
  147. boost::polymorphic_get<T>(*v); // Must compile
  148. boost::polymorphic_get<const T>(*v); // Must compile
  149. boost::polymorphic_strict_get<T>(*v); // Must compile
  150. boost::polymorphic_strict_get<const T>(*v); // Must compile
  151. }
  152. }
  153. template <class T, class V>
  154. inline void check_get_on_types(V* v)
  155. {
  156. check_get_on_types_impl<T, V>(v);
  157. check_get_on_types_impl<T, const V>(v);
  158. }
  159. inline void get_test()
  160. {
  161. var_t v;
  162. check_get_on_types<int>(&v);
  163. var_t(base()).swap(v);
  164. check_get_on_types<base>(&v);
  165. var_t(derived1()).swap(v);
  166. check_get_on_types<derived1>(&v);
  167. var_t(derived2()).swap(v);
  168. check_get_on_types<derived2>(&v);
  169. var_t(std::string("Hello")).swap(v);
  170. check_get_on_types<std::string>(&v);
  171. var_t_shortened vs = derived2();
  172. check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs);
  173. check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs);
  174. // Checking that Base is really determinated
  175. check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs);
  176. check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs);
  177. vs = derived1();
  178. check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs);
  179. check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs);
  180. // Checking that Base is really determinated
  181. check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs);
  182. check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs);
  183. }
  184. inline void get_test_no_fallback()
  185. {
  186. var_t_no_fallback v;
  187. var_t_no_fallback(base()).swap(v);
  188. check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
  189. check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
  190. check_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
  191. check_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
  192. var_t_no_fallback(derived1()).swap(v);
  193. check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
  194. check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
  195. check_get_on_types_impl_single_type<derived1, var_t_no_fallback, derived1>(&v);
  196. check_get_on_types_impl_single_type<derived1, const var_t_no_fallback, derived1>(&v);
  197. var_t_no_fallback(derived2()).swap(v);
  198. check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
  199. check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
  200. check_get_on_types_impl_single_type<derived2, var_t_no_fallback, derived2>(&v);
  201. check_get_on_types_impl_single_type<derived2, const var_t_no_fallback, derived2>(&v);
  202. }
  203. inline void get_ref_test()
  204. {
  205. int i = 0;
  206. var_ref_t v(i);
  207. check_get_on_types<int>(&v);
  208. check_get_on_types<int&>(&v);
  209. base b;
  210. var_ref_t v1(b);
  211. check_get_on_types<base>(&v1);
  212. check_get_on_types<base&>(&v1);
  213. derived1 d1;
  214. var_ref_t v2(d1);
  215. check_get_on_types<derived1>(&v2);
  216. check_get_on_types<derived1&>(&v2);
  217. derived2 d2;
  218. var_ref_t v3(d2);
  219. check_get_on_types<derived2>(&v3);
  220. check_get_on_types<derived2&>(&v3);
  221. std::string s("Hello");
  222. var_ref_t v4(s);
  223. check_get_on_types<std::string>(&v4);
  224. check_get_on_types<std::string&>(&v4);
  225. }
  226. inline void get_cref_test()
  227. {
  228. int i = 0;
  229. var_cref_t v(i);
  230. BOOST_TEST(boost::get<const int>(&v));
  231. BOOST_TEST(boost::get<const int&>(&v));
  232. BOOST_TEST(!boost::get<const base>(&v));
  233. base b;
  234. var_cref_t v1(b);
  235. BOOST_TEST(boost::get<const base>(&v1));
  236. BOOST_TEST(!boost::get<const derived1>(&v1));
  237. BOOST_TEST(!boost::get<const int>(&v1));
  238. std::string s("Hello");
  239. const var_cref_t v4 = s;
  240. BOOST_TEST(boost::get<const std::string>(&v4));
  241. BOOST_TEST(!boost::get<const int>(&v4));
  242. }
  243. inline void get_recursive_test()
  244. {
  245. var_req_t v;
  246. check_get_on_types<int>(&v);
  247. var_req_t(base()).swap(v);
  248. check_get_on_types<base>(&v);
  249. var_req_t(derived1()).swap(v);
  250. check_get_on_types<derived1>(&v);
  251. var_req_t(derived2()).swap(v);
  252. check_get_on_types<derived2>(&v);
  253. var_req_t(std::string("Hello")).swap(v);
  254. check_get_on_types<std::string>(&v);
  255. recursive_structure s = { v }; // copying "v"
  256. v = s;
  257. check_get_on_types<recursive_structure>(&v);
  258. }
  259. template <class T>
  260. inline void check_that_does_not_exist_impl()
  261. {
  262. using namespace boost::detail::variant;
  263. BOOST_TEST((holds_element<T, const int>::value));
  264. BOOST_TEST((!holds_element<T, short>::value));
  265. BOOST_TEST((!holds_element<T, short>::value));
  266. BOOST_TEST((!holds_element<T, const short>::value));
  267. BOOST_TEST((!holds_element<T, char*>::value));
  268. BOOST_TEST((!holds_element<T, const char*>::value));
  269. BOOST_TEST((!holds_element<T, char[5]>::value));
  270. BOOST_TEST((!holds_element<T, const char[5]>::value));
  271. BOOST_TEST((!holds_element<T, bool>::value));
  272. BOOST_TEST((!holds_element<T, const bool>::value));
  273. BOOST_TEST((!holds_element<T, boost::recursive_wrapper<int> >::value));
  274. BOOST_TEST((!holds_element<T, boost::recursive_wrapper<short> >::value));
  275. BOOST_TEST((!holds_element<T, boost::detail::reference_content<short> >::value));
  276. BOOST_TEST((holds_element_polymorphic<T, const int>::value));
  277. BOOST_TEST((!holds_element_polymorphic<T, short>::value));
  278. BOOST_TEST((!holds_element_polymorphic<T, short>::value));
  279. BOOST_TEST((!holds_element_polymorphic<T, const short>::value));
  280. BOOST_TEST((!holds_element_polymorphic<T, char*>::value));
  281. BOOST_TEST((!holds_element_polymorphic<T, const char*>::value));
  282. BOOST_TEST((!holds_element_polymorphic<T, char[5]>::value));
  283. BOOST_TEST((!holds_element_polymorphic<T, const char[5]>::value));
  284. BOOST_TEST((!holds_element_polymorphic<T, bool>::value));
  285. BOOST_TEST((!holds_element_polymorphic<T, const bool>::value));
  286. BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<int> >::value));
  287. BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<short> >::value));
  288. BOOST_TEST((!holds_element_polymorphic<T, boost::detail::reference_content<short> >::value));
  289. }
  290. inline void check_that_does_not_exist()
  291. {
  292. using namespace boost::detail::variant;
  293. BOOST_TEST((holds_element<var_t, int>::value));
  294. BOOST_TEST((holds_element<var_ref_t, int>::value));
  295. BOOST_TEST((!holds_element<var_cref_t, int>::value));
  296. check_that_does_not_exist_impl<var_t>();
  297. check_that_does_not_exist_impl<var_ref_t>();
  298. check_that_does_not_exist_impl<var_cref_t>();
  299. check_that_does_not_exist_impl<var_req_t>();
  300. }
  301. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  302. class MoveonlyType {
  303. public:
  304. MoveonlyType() {}
  305. ~MoveonlyType() {}
  306. MoveonlyType(MoveonlyType&&) {}
  307. void operator=(MoveonlyType&&) {}
  308. private:
  309. MoveonlyType(const MoveonlyType&);
  310. void operator=(const MoveonlyType&);
  311. };
  312. const boost::variant<int, std::string> foo1() { return ""; }
  313. boost::variant<int, std::string> foo2() { return ""; }
  314. inline void get_rvref_test()
  315. {
  316. boost::get<std::string>(foo1());
  317. boost::get<std::string>(foo2());
  318. boost::variant<MoveonlyType, int> v;
  319. v = MoveonlyType();
  320. boost::get<MoveonlyType>(boost::move(v));
  321. v = 3;
  322. v = MoveonlyType();
  323. boost::get<MoveonlyType>(v);
  324. boost::relaxed_get<MoveonlyType&>(boost::variant<MoveonlyType, int>());
  325. v = MoveonlyType();
  326. MoveonlyType moved_from_variant(boost::get<MoveonlyType>(boost::move(v)));
  327. }
  328. #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
  329. int main()
  330. {
  331. get_test();
  332. get_test_no_fallback();
  333. get_ref_test();
  334. get_cref_test();
  335. get_recursive_test();
  336. check_that_does_not_exist();
  337. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  338. get_rvref_test();
  339. #endif
  340. return boost::report_errors();
  341. }