//----------------------------------------------------------------------------- // boost-libs variant/test/variant_get_test.cpp source file // See http://www.boost.org for updates, documentation, and revision history. //----------------------------------------------------------------------------- // // Copyright (c) 2016-2019 Antony Polukhin // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // This test suite was created to cover issues reported in: // https://svn.boost.org/trac/boost/ticket/5871 // https://svn.boost.org/trac/boost/ticket/11602 #include "boost/variant/variant.hpp" #include "boost/variant/recursive_variant.hpp" #include "boost/core/lightweight_test.hpp" #include #include struct A{}; struct B{}; struct C{}; struct D{}; bool foo(const boost::variant& ) { return false; } bool foo(const boost::variant& ) { return true; } void test_overload_selection_variant_constructor() { D d; BOOST_TEST(foo(d)); boost::variant v; BOOST_TEST(!foo(v)); } // Pre msvc-14.0 could not dustinguish between multiple assignment operators: // warning C4522: 'assignment_tester' : multiple assignment operators specified // error C2666: variant::operator =' : 3 overloads have similar conversions // Old versions of GCC have same issue: // error: variant::operator=(const T&) cannot be overloaded #if (defined(__GNUC__) && (__GNUC__ < 4)) || (defined(_MSC_VER) && _MSC_VER < 1900) void test_overload_selection_variant_assignment() { BOOST_TEST(true); } #else struct assignment_tester: boost::variant, boost::variant { using boost::variant::operator=; using boost::variant::operator=; }; void test_overload_selection_variant_assignment() { A a; assignment_tester tester; tester = a; const int which0 = static_cast< boost::variant& >(tester).which(); BOOST_TEST(which0 == 1); boost::variant b; b = B(); tester = b; const int which1 = static_cast< boost::variant& >(tester).which(); BOOST_TEST(which1 == 0); } #endif typedef boost::variant my_variant; struct convertible { operator my_variant() const { return my_variant(); } }; void test_implicit_conversion_operator() { // https://svn.boost.org/trac/boost/ticket/8555 my_variant y = convertible(); BOOST_TEST(y.which() == 0); } struct X: boost::variant< int > {}; class V1: public boost::variant {}; struct AB: boost::variant {}; void test_derived_from_variant_construction() { // https://svn.boost.org/trac/boost/ticket/7120 X x; boost::variant y(x); BOOST_TEST(y.which() == 0); // https://svn.boost.org/trac/boost/ticket/10278 boost::variant v2 = V1(); BOOST_TEST(v2.which() == 0); // https://svn.boost.org/trac/boost/ticket/12155 AB ab; boost::variant ab_c(ab); BOOST_TEST(ab_c.which() == 0); boost::variant a_b(ab); BOOST_TEST(a_b.which() == 0); boost::variant b_c_a1(static_cast& >(ab)); BOOST_TEST(b_c_a1.which() == 2); // Following conversion seems harmful as it may lead to slicing: // boost::variant b_c_a(ab); // BOOST_TEST(b_c_a.which() == 2); } void test_derived_from_variant_assignment() { // https://svn.boost.org/trac/boost/ticket/7120 X x; boost::variant y; y = x; BOOST_TEST(y.which() == 0); // https://svn.boost.org/trac/boost/ticket/10278 boost::variant v2; v2 = V1(); BOOST_TEST(v2.which() == 0); // https://svn.boost.org/trac/boost/ticket/12155 AB ab; boost::variant ab_c; ab_c = ab; BOOST_TEST(ab_c.which() == 0); boost::variant a_b; a_b = ab; BOOST_TEST(a_b.which() == 0); boost::variant b_c_a1; b_c_a1 = static_cast& >(ab); BOOST_TEST(b_c_a1.which() == 2); // Following conversion seems harmful as it may lead to slicing: // boost::variant b_c_a; // b_c_a = ab; // BOOST_TEST(b_c_a.which() == 2); } // http://thread.gmane.org/gmane.comp.lib.boost.devel/267757 struct info { struct nil_ {}; typedef boost::variant< nil_ , std::string , boost::recursive_wrapper , boost::recursive_wrapper > , boost::recursive_wrapper > > value_type; value_type v; inline void test_on_incomplete_types() { info i0; i0.v = "Hello"; BOOST_TEST(i0.v.which() == 1); info::value_type v0 = "Hello"; BOOST_TEST(v0.which() == 1); info::value_type v1("Hello"); BOOST_TEST(v1.which() == 1); info::value_type v2 = i0; BOOST_TEST(v2.which() == 2); info::value_type v3(i0); BOOST_TEST(v3.which() == 2); v0 = v3; BOOST_TEST(v0.which() == 2); v3 = v1; BOOST_TEST(v3.which() == 1); v3 = nil_(); BOOST_TEST(v3.which() == 0); } }; int main() { test_overload_selection_variant_constructor(); test_overload_selection_variant_assignment(); test_implicit_conversion_operator(); test_derived_from_variant_construction(); test_derived_from_variant_assignment(); info().test_on_incomplete_types(); return boost::report_errors(); }