variant.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2015-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. #include <vector>
  12. #include <sstream>
  13. #include <iostream>
  14. #include <range/v3/functional/overload.hpp>
  15. #include <range/v3/numeric/accumulate.hpp>
  16. #include <range/v3/utility/variant.hpp>
  17. #include <range/v3/view/concat.hpp>
  18. #include <range/v3/view/partial_sum.hpp>
  19. #include <range/v3/view/transform.hpp>
  20. #include "../simple_test.hpp"
  21. #include "../test_utils.hpp"
  22. void bug_1217()
  23. {
  24. std::vector<int> vec;
  25. if(auto tx = vec | ranges::views::transform( [](int){ return 0; } ))
  26. {
  27. auto positions_visited = ranges::views::concat( tx, tx ) | ranges::views::partial_sum;
  28. ranges::accumulate( positions_visited, 0 );
  29. }
  30. }
  31. int main()
  32. {
  33. using namespace ranges;
  34. // Simple variant and access.
  35. {
  36. variant<int, short> v;
  37. CHECK(v.index() == 0u);
  38. auto v2 = v;
  39. CHECK(v2.index() == 0u);
  40. v.emplace<1>((short)2);
  41. CHECK(v.index() == 1u);
  42. CHECK(get<1>(v) == (short)2);
  43. try
  44. {
  45. get<0>(v);
  46. CHECK(false);
  47. }
  48. catch(const bad_variant_access&)
  49. {}
  50. catch(...)
  51. {
  52. CHECK(!(bool)"unknown exception");
  53. }
  54. v = v2;
  55. CHECK(v.index() == 0u);
  56. }
  57. // variant of void
  58. {
  59. variant<void, void> v;
  60. CHECK(v.index() == 0u);
  61. v.emplace<0>();
  62. CHECK(v.index() == 0u);
  63. try
  64. {
  65. // Will only compile if get returns void
  66. v.index() == 0 ? void() : get<0>(v);
  67. }
  68. catch(...)
  69. {
  70. CHECK(false);
  71. }
  72. v.emplace<1>();
  73. CHECK(v.index() == 1u);
  74. try
  75. {
  76. get<0>(v);
  77. CHECK(false);
  78. }
  79. catch(const bad_variant_access&)
  80. {}
  81. catch(...)
  82. {
  83. CHECK(!(bool)"unknown exception");
  84. }
  85. }
  86. // variant of references
  87. {
  88. int i = 42;
  89. std::string s = "hello world";
  90. variant<int&, std::string&> v{emplaced_index<0>, i};
  91. CPP_assert(!default_constructible<variant<int&, std::string&>>);
  92. CHECK(v.index() == 0u);
  93. CHECK(get<0>(v) == 42);
  94. CHECK(&get<0>(v) == &i);
  95. auto const & cv = v;
  96. get<0>(cv) = 24;
  97. CHECK(i == 24);
  98. v.emplace<1>(s);
  99. CHECK(v.index() == 1u);
  100. CHECK(get<1>(v) == "hello world");
  101. CHECK(&get<1>(v) == &s);
  102. get<1>(cv) = "goodbye";
  103. CHECK(s == "goodbye");
  104. }
  105. // Move test 1
  106. {
  107. variant<int, MoveOnlyString> v{emplaced_index<1>, "hello world"};
  108. CHECK(get<1>(v) == "hello world");
  109. MoveOnlyString s = get<1>(std::move(v));
  110. CHECK(s == "hello world");
  111. CHECK(get<1>(v) == "");
  112. v.emplace<1>("goodbye");
  113. CHECK(get<1>(v) == "goodbye");
  114. auto v2 = std::move(v);
  115. CHECK(get<1>(v2) == "goodbye");
  116. CHECK(get<1>(v) == "");
  117. v = std::move(v2);
  118. CHECK(get<1>(v) == "goodbye");
  119. CHECK(get<1>(v2) == "");
  120. }
  121. // Move test 2
  122. {
  123. MoveOnlyString s = "hello world";
  124. variant<MoveOnlyString&> v{emplaced_index<0>, s};
  125. CHECK(get<0>(v) == "hello world");
  126. MoveOnlyString &s2 = get<0>(std::move(v));
  127. CHECK(&s2 == &s);
  128. }
  129. // Apply test 1
  130. {
  131. std::stringstream sout;
  132. variant<int, std::string> v{emplaced_index<1>, "hello"};
  133. auto fun = overload(
  134. [&sout](int&) {sout << "int";},
  135. [&sout](std::string&)->int {sout << "string"; return 42;});
  136. variant<void, int> x = v.visit(fun);
  137. CHECK(sout.str() == "string");
  138. CHECK(x.index() == 1u);
  139. CHECK(get<1>(x) == 42);
  140. }
  141. // Apply test 2
  142. {
  143. std::stringstream sout;
  144. std::string s = "hello";
  145. variant<int, std::string&> const v{emplaced_index<1>, s};
  146. auto fun = overload(
  147. [&sout](int const&) {sout << "int";},
  148. [&sout](std::string&)->int {sout << "string"; return 42;});
  149. variant<void, int> x = v.visit(fun);
  150. CHECK(sout.str() == "string");
  151. CHECK(x.index() == 1u);
  152. CHECK(get<1>(x) == 42);
  153. }
  154. // constexpr variant
  155. {
  156. constexpr variant<int, short> v{emplaced_index<1>, (short)2};
  157. static_assert(v.index() == 1,"");
  158. static_assert(v.valid(),"");
  159. }
  160. // Variant and arrays
  161. {
  162. variant<int[5], std::vector<int>> v{emplaced_index<0>, {1,2,3,4,5}};
  163. int (&rgi)[5] = get<0>(v);
  164. check_equal(rgi, {1,2,3,4,5});
  165. variant<int[5], std::vector<int>> v2{emplaced_index<0>, {}};
  166. int (&rgi2)[5] = get<0>(v2);
  167. check_equal(rgi2, {0,0,0,0,0});
  168. v2 = v;
  169. check_equal(rgi2, {1,2,3,4,5});
  170. struct T
  171. {
  172. T() = delete;
  173. T(int) {}
  174. T(T const &) = default;
  175. T &operator=(T const &) = default;
  176. };
  177. // Should compile and not assert at runtime.
  178. variant<T[5]> vrgt{emplaced_index<0>, {T{42},T{42},T{42},T{42},T{42}}};
  179. (void) vrgt;
  180. }
  181. return ::test_result();
  182. }