overload_selection.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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) 2016-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. // This test suite was created to cover issues reported in:
  12. // https://svn.boost.org/trac/boost/ticket/5871
  13. // https://svn.boost.org/trac/boost/ticket/11602
  14. #include "boost/variant/variant.hpp"
  15. #include "boost/variant/recursive_variant.hpp"
  16. #include "boost/core/lightweight_test.hpp"
  17. #include <string>
  18. #include <list>
  19. struct A{};
  20. struct B{};
  21. struct C{};
  22. struct D{};
  23. bool foo(const boost::variant<A, B>& ) {
  24. return false;
  25. }
  26. bool foo(const boost::variant<C, D>& ) {
  27. return true;
  28. }
  29. void test_overload_selection_variant_constructor() {
  30. D d;
  31. BOOST_TEST(foo(d));
  32. boost::variant<B, A> v;
  33. BOOST_TEST(!foo(v));
  34. }
  35. // Pre msvc-14.0 could not dustinguish between multiple assignment operators:
  36. // warning C4522: 'assignment_tester' : multiple assignment operators specified
  37. // error C2666: variant::operator =' : 3 overloads have similar conversions
  38. // Old versions of GCC have same issue:
  39. // error: variant::operator=(const T&) cannot be overloaded
  40. #if (defined(__GNUC__) && (__GNUC__ < 4)) || (defined(_MSC_VER) && _MSC_VER < 1900)
  41. void test_overload_selection_variant_assignment() {
  42. BOOST_TEST(true);
  43. }
  44. #else
  45. struct assignment_tester: boost::variant<C, D>, boost::variant<B, A> {
  46. using boost::variant<B, A>::operator=;
  47. using boost::variant<C, D>::operator=;
  48. };
  49. void test_overload_selection_variant_assignment() {
  50. A a;
  51. assignment_tester tester;
  52. tester = a;
  53. const int which0 = static_cast< boost::variant<B, A>& >(tester).which();
  54. BOOST_TEST(which0 == 1);
  55. boost::variant<A, B> b;
  56. b = B();
  57. tester = b;
  58. const int which1 = static_cast< boost::variant<B, A>& >(tester).which();
  59. BOOST_TEST(which1 == 0);
  60. }
  61. #endif
  62. typedef boost::variant<int> my_variant;
  63. struct convertible {
  64. operator my_variant() const {
  65. return my_variant();
  66. }
  67. };
  68. void test_implicit_conversion_operator() {
  69. // https://svn.boost.org/trac/boost/ticket/8555
  70. my_variant y = convertible();
  71. BOOST_TEST(y.which() == 0);
  72. }
  73. struct X: boost::variant< int > {};
  74. class V1: public boost::variant<float,double> {};
  75. struct AB: boost::variant<A, B> {};
  76. void test_derived_from_variant_construction() {
  77. // https://svn.boost.org/trac/boost/ticket/7120
  78. X x;
  79. boost::variant<X> y(x);
  80. BOOST_TEST(y.which() == 0);
  81. // https://svn.boost.org/trac/boost/ticket/10278
  82. boost::variant<V1, std::string> v2 = V1();
  83. BOOST_TEST(v2.which() == 0);
  84. // https://svn.boost.org/trac/boost/ticket/12155
  85. AB ab;
  86. boost::variant<AB, C> ab_c(ab);
  87. BOOST_TEST(ab_c.which() == 0);
  88. boost::variant<A, B> a_b(ab);
  89. BOOST_TEST(a_b.which() == 0);
  90. boost::variant<B, C, A> b_c_a1(static_cast<boost::variant<A, B>& >(ab));
  91. BOOST_TEST(b_c_a1.which() == 2);
  92. // Following conversion seems harmful as it may lead to slicing:
  93. // boost::variant<B, C, A> b_c_a(ab);
  94. // BOOST_TEST(b_c_a.which() == 2);
  95. }
  96. void test_derived_from_variant_assignment() {
  97. // https://svn.boost.org/trac/boost/ticket/7120
  98. X x;
  99. boost::variant<X> y;
  100. y = x;
  101. BOOST_TEST(y.which() == 0);
  102. // https://svn.boost.org/trac/boost/ticket/10278
  103. boost::variant<V1, std::string> v2;
  104. v2 = V1();
  105. BOOST_TEST(v2.which() == 0);
  106. // https://svn.boost.org/trac/boost/ticket/12155
  107. AB ab;
  108. boost::variant<AB, C> ab_c;
  109. ab_c = ab;
  110. BOOST_TEST(ab_c.which() == 0);
  111. boost::variant<A, B> a_b;
  112. a_b = ab;
  113. BOOST_TEST(a_b.which() == 0);
  114. boost::variant<B, C, A> b_c_a1;
  115. b_c_a1 = static_cast<boost::variant<A, B>& >(ab);
  116. BOOST_TEST(b_c_a1.which() == 2);
  117. // Following conversion seems harmful as it may lead to slicing:
  118. // boost::variant<B, C, A> b_c_a;
  119. // b_c_a = ab;
  120. // BOOST_TEST(b_c_a.which() == 2);
  121. }
  122. // http://thread.gmane.org/gmane.comp.lib.boost.devel/267757
  123. struct info {
  124. struct nil_ {};
  125. typedef
  126. boost::variant<
  127. nil_
  128. , std::string
  129. , boost::recursive_wrapper<info>
  130. , boost::recursive_wrapper<std::pair<info, info> >
  131. , boost::recursive_wrapper<std::list<info> >
  132. >
  133. value_type;
  134. value_type v;
  135. inline void test_on_incomplete_types() {
  136. info i0;
  137. i0.v = "Hello";
  138. BOOST_TEST(i0.v.which() == 1);
  139. info::value_type v0 = "Hello";
  140. BOOST_TEST(v0.which() == 1);
  141. info::value_type v1("Hello");
  142. BOOST_TEST(v1.which() == 1);
  143. info::value_type v2 = i0;
  144. BOOST_TEST(v2.which() == 2);
  145. info::value_type v3(i0);
  146. BOOST_TEST(v3.which() == 2);
  147. v0 = v3;
  148. BOOST_TEST(v0.which() == 2);
  149. v3 = v1;
  150. BOOST_TEST(v3.which() == 1);
  151. v3 = nil_();
  152. BOOST_TEST(v3.which() == 0);
  153. }
  154. };
  155. int main()
  156. {
  157. test_overload_selection_variant_constructor();
  158. test_overload_selection_variant_assignment();
  159. test_implicit_conversion_operator();
  160. test_derived_from_variant_construction();
  161. test_derived_from_variant_assignment();
  162. info().test_on_incomplete_types();
  163. return boost::report_errors();
  164. }