recursive_variant_test.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. //-----------------------------------------------------------------------------
  2. // boost-libs variant/test/recursive_variant_test.cpp source file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2003 Eric Friedman, Itay Maman
  7. // Copyright (c) 2013-2019 Antony Polukhin
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. // This file is used in two test cases:
  13. //
  14. // 1) recursive_variant_test.cpp that tests recursive usage of variant
  15. //
  16. // 2) variant_noexcept_test that tests Boost.Variant ability to compile
  17. // and work with disabled exceptions
  18. #include "boost/core/lightweight_test.hpp"
  19. #include "boost/variant.hpp"
  20. #include "boost/mpl/vector.hpp"
  21. #include "boost/mpl/copy.hpp"
  22. #include <iostream>
  23. #include <sstream>
  24. #include <vector>
  25. #include <map>
  26. #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  27. #include <tuple>
  28. #endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  29. struct printer
  30. : boost::static_visitor<std::string>
  31. {
  32. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  33. std::string operator()(
  34. const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &var) const
  35. {
  36. return boost::apply_visitor( printer(), var );
  37. }
  38. template <typename T>
  39. std::string operator()(const std::vector<T>& vec) const
  40. {
  41. std::ostringstream ost;
  42. ost << "( ";
  43. typename std::vector<T>::const_iterator it = vec.begin();
  44. for (; it != vec.end(); ++it)
  45. ost << printer()( *it );
  46. ost << ") ";
  47. return ost.str();
  48. }
  49. #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  50. template <int...> struct indices {};
  51. template <typename... Ts, int... Is>
  52. std::string operator()(const std::tuple<Ts...>& tup, indices<Is...>) const
  53. {
  54. std::ostringstream ost;
  55. ost << "( ";
  56. int a[] = {0, (ost << printer()( std::get<Is>(tup) ), 0)... };
  57. (void)a;
  58. ost << ") ";
  59. return ost.str();
  60. }
  61. template <int N, int... Is>
  62. struct make_indices : make_indices<N-1, N-1, Is...> {};
  63. template <int... Is>
  64. struct make_indices<0, Is...> : indices<Is...> {};
  65. template <typename... Ts>
  66. std::string operator()(const std::tuple<Ts...>& tup) const
  67. {
  68. return printer()(tup, make_indices<sizeof...(Ts)>());
  69. }
  70. #endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  71. template <typename T>
  72. std::string operator()(const T& operand) const
  73. {
  74. std::ostringstream ost;
  75. ost << operand << ' ';
  76. return ost.str();
  77. }
  78. };
  79. void test_recursive_variant()
  80. {
  81. typedef boost::make_recursive_variant<
  82. int
  83. , std::vector<boost::recursive_variant_>
  84. >::type var1_t;
  85. std::vector<var1_t> vec1;
  86. vec1.push_back(3);
  87. vec1.push_back(5);
  88. vec1.push_back(vec1);
  89. vec1.push_back(7);
  90. var1_t var1(vec1);
  91. std::string result1( printer()(var1) );
  92. std::cout << "result1: " << result1 << '\n';
  93. BOOST_TEST(result1 == "( 3 5 ( 3 5 ) 7 ) ");
  94. std::vector<var1_t> vec1_copy = vec1;
  95. vec1_copy.erase(vec1_copy.begin() + 2);
  96. vec1_copy.insert(vec1_copy.begin() + 2, vec1_copy);
  97. var1 = vec1_copy;
  98. result1 = printer()(var1);
  99. std::cout << "result1+: " << result1 << '\n';
  100. BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
  101. // Uses move construction on compilers with rvalue references support
  102. result1 = printer()(
  103. var1_t(
  104. std::vector<var1_t>(vec1_copy)
  105. )
  106. );
  107. std::cout << "result1++: " << result1 << '\n';
  108. BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
  109. var1_t vec1_another_copy(vec1_copy);
  110. vec1_copy[2].swap(vec1_another_copy);
  111. result1 = printer()(
  112. var1_t(vec1_copy)
  113. );
  114. std::cout << "result1+++1: " << result1 << '\n';
  115. BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) ");
  116. result1 = printer()(vec1_another_copy);
  117. std::cout << "result1++2: " << result1 << '\n';
  118. BOOST_TEST(result1 == "( 3 5 7 ) ");
  119. vec1_copy[2].swap(vec1_copy[2]);
  120. result1 = printer()(
  121. var1_t(vec1_copy)
  122. );
  123. std::cout << "result1.2: " << result1 << '\n';
  124. BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) ");
  125. typedef boost::make_recursive_variant<
  126. boost::variant<int, double>
  127. , std::vector<boost::recursive_variant_>
  128. >::type var2_t;
  129. std::vector<var2_t> vec2;
  130. vec2.push_back(boost::variant<int, double>(3));
  131. vec2.push_back(boost::variant<int, double>(3.5));
  132. vec2.push_back(vec2);
  133. vec2.push_back(boost::variant<int, double>(7));
  134. var2_t var2(vec2);
  135. std::string result2( printer()(var2) );
  136. std::cout << "result2: " << result2 << '\n';
  137. BOOST_TEST(result2 == "( 3 3.5 ( 3 3.5 ) 7 ) ");
  138. typedef boost::make_recursive_variant<
  139. int
  140. , std::vector<
  141. boost::variant<
  142. double
  143. , std::vector<boost::recursive_variant_>
  144. >
  145. >
  146. >::type var3_t;
  147. typedef boost::variant<double, std::vector<var3_t> > var4_t;
  148. std::vector<var3_t> vec3;
  149. vec3.push_back(3);
  150. vec3.push_back(5);
  151. std::vector<var4_t> vec4;
  152. vec4.push_back(3.5);
  153. vec4.push_back(vec3);
  154. vec3.push_back(vec4);
  155. vec3.push_back(7);
  156. var4_t var4(vec3);
  157. std::string result3( printer()(var4) );
  158. std::cout << "result2: " << result3 << '\n';
  159. BOOST_TEST(result3 == "( 3 5 ( 3.5 ( 3 5 ) ) 7 ) ");
  160. typedef boost::make_recursive_variant<
  161. double,
  162. std::vector<var1_t>
  163. >::type var5_t;
  164. std::vector<var5_t> vec5;
  165. vec5.push_back(3.5);
  166. vec5.push_back(vec1);
  167. vec5.push_back(17.25);
  168. std::string result5( printer()(vec5) );
  169. std::cout << "result5: " << result5 << '\n';
  170. BOOST_TEST(result5 == "( 3.5 ( 3 5 ( 3 5 ) 7 ) 17.25 ) ");
  171. typedef boost::make_recursive_variant<
  172. int,
  173. std::map<int, boost::recursive_variant_>
  174. >::type var6_t;
  175. var6_t var6;
  176. #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  177. typedef boost::make_recursive_variant<
  178. int,
  179. std::tuple<int, boost::recursive_variant_>
  180. >::type var7_t;
  181. var7_t var7 = 0; // !!! Do not replace with `var7_t var7{0}` or `var7_t var7(0)` !!!
  182. var7 = std::tuple<int, var7_t>(1, var7);
  183. var7 = std::tuple<int, var7_t>(2, var7);
  184. std::string result7( printer()(var7) );
  185. std::cout << "result7: " << result7 << '\n';
  186. BOOST_TEST(result7 == "( 2 ( 1 0 ) ) ");
  187. #endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  188. }
  189. void test_recursive_variant_over()
  190. {
  191. typedef boost::make_recursive_variant_over<
  192. boost::mpl::vector<
  193. int
  194. , std::vector<boost::recursive_variant_>
  195. >
  196. >::type var1_t;
  197. std::vector<var1_t> vec1;
  198. vec1.push_back(3);
  199. vec1.push_back(5);
  200. vec1.push_back(vec1);
  201. vec1.push_back(7);
  202. var1_t var1(vec1);
  203. std::string result1( printer()(var1) );
  204. std::cout << "result1: " << result1 << '\n';
  205. BOOST_TEST(result1 == "( 3 5 ( 3 5 ) 7 ) ");
  206. std::vector<var1_t> vec1_copy = vec1;
  207. vec1_copy.erase(vec1_copy.begin() + 2);
  208. vec1_copy.insert(vec1_copy.begin() + 2, vec1_copy);
  209. var1 = vec1_copy;
  210. result1 = printer()(var1);
  211. std::cout << "result1+: " << result1 << '\n';
  212. BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
  213. // Uses move construction on compilers with rvalue references support
  214. result1 = printer()(
  215. var1_t(
  216. std::vector<var1_t>(vec1_copy)
  217. )
  218. );
  219. std::cout << "result1++: " << result1 << '\n';
  220. BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
  221. var1_t vec1_another_copy(vec1_copy);
  222. vec1_copy[2].swap(vec1_another_copy);
  223. result1 = printer()(
  224. var1_t(vec1_copy)
  225. );
  226. std::cout << "result1+++1: " << result1 << '\n';
  227. BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) ");
  228. result1 = printer()(vec1_another_copy);
  229. std::cout << "result1++2: " << result1 << '\n';
  230. BOOST_TEST(result1 == "( 3 5 7 ) ");
  231. typedef boost::make_recursive_variant_over<
  232. boost::mpl::vector<
  233. boost::make_variant_over<boost::mpl::vector<int, double> >::type
  234. , std::vector<boost::recursive_variant_>
  235. >
  236. >::type var2_t;
  237. std::vector<var2_t> vec2;
  238. vec2.push_back(boost::variant<int, double>(3));
  239. vec2.push_back(boost::variant<int, double>(3.5));
  240. vec2.push_back(vec2);
  241. vec2.push_back(boost::variant<int, double>(7));
  242. var2_t var2(vec2);
  243. std::string result2( printer()(var2) );
  244. std::cout << "result2: " << result2 << '\n';
  245. BOOST_TEST(result2 == "( 3 3.5 ( 3 3.5 ) 7 ) ");
  246. typedef boost::make_recursive_variant_over<
  247. boost::mpl::vector<
  248. int
  249. , std::vector<
  250. boost::make_variant_over<
  251. boost::mpl::vector<
  252. double
  253. , std::vector<boost::recursive_variant_>
  254. >
  255. >::type
  256. >
  257. >
  258. >::type var3_t;
  259. typedef boost::make_variant_over<
  260. boost::mpl::copy<
  261. boost::mpl::vector<
  262. double
  263. , std::vector<var3_t>
  264. >
  265. >::type
  266. >::type var4_t;
  267. std::vector<var3_t> vec3;
  268. vec3.push_back(3);
  269. vec3.push_back(5);
  270. std::vector<var4_t> vec4;
  271. vec4.push_back(3.5);
  272. vec4.push_back(vec3);
  273. vec3.push_back(vec4);
  274. vec3.push_back(7);
  275. var4_t var3(vec3);
  276. std::string result3( printer()(var3) );
  277. std::cout << "result2: " << result3 << '\n';
  278. BOOST_TEST(result3 == "( 3 5 ( 3.5 ( 3 5 ) ) 7 ) ");
  279. typedef boost::make_recursive_variant_over<
  280. boost::mpl::vector<
  281. double
  282. , std::vector<var1_t>
  283. >
  284. >::type var5_t;
  285. std::vector<var5_t> vec5;
  286. vec5.push_back(3.5);
  287. vec5.push_back(vec1);
  288. vec5.push_back(17.25);
  289. std::string result5( printer()(vec5) );
  290. std::cout << "result5: " << result5 << '\n';
  291. BOOST_TEST(result5 == "( 3.5 ( 3 5 ( 3 5 ) 7 ) 17.25 ) ");
  292. }
  293. int main()
  294. {
  295. test_recursive_variant();
  296. test_recursive_variant_over();
  297. return boost::report_errors();
  298. }