//----------------------------------------------------------------------------- // boost-libs variant/test/variant_get_test.cpp source file // See http://www.boost.org for updates, documentation, and revision history. //----------------------------------------------------------------------------- // // Copyright (c) 2014-2015 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) #include "boost/variant/get.hpp" #include "boost/variant/variant.hpp" #include "boost/variant/polymorphic_get.hpp" #include "boost/variant/recursive_wrapper.hpp" #include "boost/test/minimal.hpp" struct base { int trash; base() : trash(123) {} base(const base& b) : trash(b.trash) { int i = 100; (void)i; } const base& operator=(const base& b) { trash = b.trash; int i = 100; (void)i; return *this; } virtual ~base(){} }; struct derived1 : base{}; struct derived2 : base{}; struct vbase { short trash; virtual ~vbase(){} virtual int foo() const { return 0; } }; struct vderived1 : virtual vbase{ virtual int foo() const { return 1; } }; struct vderived2 : virtual vbase{ virtual int foo() const { return 3; } }; struct vderived3 : vderived1, vderived2 { virtual int foo() const { return 3; } }; typedef boost::variant var_t; typedef boost::variant var_t_shortened; typedef boost::variant var_t_no_fallback; typedef boost::variant var_ref_t; typedef boost::variant var_cref_t; struct recursive_structure; typedef boost::variant< int, base, derived1, derived2, std::string, boost::recursive_wrapper > var_req_t; struct recursive_structure { var_req_t var; }; template inline void check_polymorphic_get_on_types_impl_single_type(V* v) { if (!!boost::is_same::value) { BOOST_CHECK(boost::polymorphic_get(v)); BOOST_CHECK(boost::polymorphic_get(v)); BOOST_CHECK(boost::polymorphic_strict_get(v)); BOOST_CHECK(boost::polymorphic_strict_get(v)); BOOST_CHECK(boost::polymorphic_relaxed_get(v)); BOOST_CHECK(boost::polymorphic_relaxed_get(v)); } else { BOOST_CHECK(!boost::polymorphic_get(v)); BOOST_CHECK(!boost::polymorphic_get(v)); BOOST_CHECK(!boost::polymorphic_strict_get(v)); BOOST_CHECK(!boost::polymorphic_strict_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); } } template inline void check_get_on_types_impl_single_type(V* v) { if (!!boost::is_same::value) { BOOST_CHECK(boost::get(v)); BOOST_CHECK(boost::get(v)); BOOST_CHECK(boost::strict_get(v)); BOOST_CHECK(boost::strict_get(v)); BOOST_CHECK(boost::relaxed_get(v)); BOOST_CHECK(boost::relaxed_get(v)); } else { BOOST_CHECK(!boost::get(v)); BOOST_CHECK(!boost::get(v)); BOOST_CHECK(!boost::strict_get(v)); BOOST_CHECK(!boost::strict_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); } } template inline void check_get_on_types_impl(V* v) { check_get_on_types_impl_single_type(v); check_polymorphic_get_on_types_impl_single_type(v); check_get_on_types_impl_single_type(v); check_get_on_types_impl_single_type(v); check_polymorphic_get_on_types_impl_single_type(v); check_get_on_types_impl_single_type(v); check_polymorphic_get_on_types_impl_single_type(v); check_get_on_types_impl_single_type(v); check_polymorphic_get_on_types_impl_single_type(v); // Never exist in here BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); BOOST_CHECK(!boost::polymorphic_relaxed_get(v)); boost::get(*v); // Must compile boost::get(*v); // Must compile boost::strict_get(*v); // Must compile boost::strict_get(*v); // Must compile boost::polymorphic_get(*v); // Must compile boost::polymorphic_get(*v); // Must compile boost::polymorphic_strict_get(*v); // Must compile boost::polymorphic_strict_get(*v); // Must compile } template inline void check_get_on_types(V* v) { check_get_on_types_impl(v); check_get_on_types_impl(v); } inline void get_test() { var_t v; check_get_on_types(&v); var_t(base()).swap(v); check_get_on_types(&v); var_t(derived1()).swap(v); check_get_on_types(&v); var_t(derived2()).swap(v); check_get_on_types(&v); var_t(std::string("Hello")).swap(v); check_get_on_types(&v); var_t_shortened vs = derived2(); check_polymorphic_get_on_types_impl_single_type(&vs); check_polymorphic_get_on_types_impl_single_type(&vs); // Checking that Base is really determinated check_polymorphic_get_on_types_impl_single_type(&vs); check_polymorphic_get_on_types_impl_single_type(&vs); vs = derived1(); check_polymorphic_get_on_types_impl_single_type(&vs); check_polymorphic_get_on_types_impl_single_type(&vs); // Checking that Base is really determinated check_polymorphic_get_on_types_impl_single_type(&vs); check_polymorphic_get_on_types_impl_single_type(&vs); } inline void get_test_no_fallback() { var_t_no_fallback v; var_t_no_fallback(base()).swap(v); check_polymorphic_get_on_types_impl_single_type(&v); check_polymorphic_get_on_types_impl_single_type(&v); check_get_on_types_impl_single_type(&v); check_get_on_types_impl_single_type(&v); var_t_no_fallback(derived1()).swap(v); check_polymorphic_get_on_types_impl_single_type(&v); check_polymorphic_get_on_types_impl_single_type(&v); check_get_on_types_impl_single_type(&v); check_get_on_types_impl_single_type(&v); var_t_no_fallback(derived2()).swap(v); check_polymorphic_get_on_types_impl_single_type(&v); check_polymorphic_get_on_types_impl_single_type(&v); check_get_on_types_impl_single_type(&v); check_get_on_types_impl_single_type(&v); } inline void get_ref_test() { int i = 0; var_ref_t v(i); check_get_on_types(&v); base b; var_ref_t v1(b); check_get_on_types(&v1); derived1 d1; var_ref_t v2(d1); check_get_on_types(&v2); derived2 d2; var_ref_t v3(d2); check_get_on_types(&v3); std::string s("Hello"); var_ref_t v4(s); check_get_on_types(&v4); } inline void get_cref_test() { int i = 0; var_cref_t v(i); BOOST_CHECK(boost::get(&v)); BOOST_CHECK(!boost::get(&v)); base b; var_cref_t v1(b); BOOST_CHECK(boost::get(&v1)); BOOST_CHECK(!boost::get(&v1)); BOOST_CHECK(!boost::get(&v1)); std::string s("Hello"); const var_cref_t v4 = s; BOOST_CHECK(boost::get(&v4)); BOOST_CHECK(!boost::get(&v4)); } inline void get_recursive_test() { var_req_t v; check_get_on_types(&v); var_req_t(base()).swap(v); check_get_on_types(&v); var_req_t(derived1()).swap(v); check_get_on_types(&v); var_req_t(derived2()).swap(v); check_get_on_types(&v); var_req_t(std::string("Hello")).swap(v); check_get_on_types(&v); recursive_structure s = { v }; // copying "v" v = s; check_get_on_types(&v); } template inline void check_that_does_not_exist_impl() { using namespace boost::detail::variant; BOOST_CHECK((holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element::value)); BOOST_CHECK((!holds_element >::value)); BOOST_CHECK((!holds_element >::value)); BOOST_CHECK((!holds_element >::value)); BOOST_CHECK((holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic::value)); BOOST_CHECK((!holds_element_polymorphic >::value)); BOOST_CHECK((!holds_element_polymorphic >::value)); BOOST_CHECK((!holds_element_polymorphic >::value)); } inline void check_that_does_not_exist() { using namespace boost::detail::variant; BOOST_CHECK((holds_element::value)); BOOST_CHECK((holds_element::value)); BOOST_CHECK((!holds_element::value)); check_that_does_not_exist_impl(); check_that_does_not_exist_impl(); check_that_does_not_exist_impl(); check_that_does_not_exist_impl(); } int test_main(int , char* []) { get_test(); get_test_no_fallback(); get_ref_test(); get_cref_test(); get_recursive_test(); check_that_does_not_exist(); return boost::exit_success; }