//----------------------------------------------------------------------------- // boost-libs variant/test/variant_get_test.cpp source file // See http://www.boost.org for updates, documentation, and revision history. //----------------------------------------------------------------------------- // // Copyright (c) 2014-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) #ifdef _MSC_VER #pragma warning(disable: 4127) // conditional expression is constant #pragma warning(disable: 4181) // qualifier applied to reference type; ignored #endif #include "boost/variant/get.hpp" #include "boost/variant/variant.hpp" #include "boost/variant/polymorphic_get.hpp" #include "boost/variant/recursive_wrapper.hpp" #include "boost/core/lightweight_test.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) { typedef typename boost::add_reference::type ref_test_t; typedef typename boost::add_reference::type cref_test_t; const bool exact_same = !!boost::is_same::value; const bool ref_same = !!boost::is_same::value; if (exact_same || ref_same) { BOOST_TEST(boost::polymorphic_get(v)); BOOST_TEST(boost::polymorphic_get(v)); BOOST_TEST(boost::polymorphic_strict_get(v)); BOOST_TEST(boost::polymorphic_strict_get(v)); BOOST_TEST(boost::polymorphic_relaxed_get(v)); BOOST_TEST(boost::polymorphic_relaxed_get(v)); BOOST_TEST(boost::polymorphic_get(v)); BOOST_TEST(boost::polymorphic_strict_get(v)); BOOST_TEST(boost::polymorphic_relaxed_get(v)); if (ref_same) { BOOST_TEST(boost::polymorphic_get(v)); BOOST_TEST(boost::polymorphic_get(v)); BOOST_TEST(boost::polymorphic_strict_get(v)); BOOST_TEST(boost::polymorphic_strict_get(v)); BOOST_TEST(boost::polymorphic_relaxed_get(v)); BOOST_TEST(boost::polymorphic_relaxed_get(v)); } } else { BOOST_TEST(!boost::polymorphic_get(v)); BOOST_TEST(!boost::polymorphic_get(v)); BOOST_TEST(!boost::polymorphic_strict_get(v)); BOOST_TEST(!boost::polymorphic_strict_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); } } template inline void check_get_on_types_impl_single_type(V* v) { typedef typename boost::add_reference::type ref_test_t; typedef typename boost::add_reference::type cref_test_t; const bool exact_same = !!boost::is_same::value; const bool ref_same = !!boost::is_same::value; if (exact_same || ref_same) { BOOST_TEST(boost::get(v)); BOOST_TEST(boost::get(v)); BOOST_TEST(boost::strict_get(v)); BOOST_TEST(boost::strict_get(v)); BOOST_TEST(boost::relaxed_get(v)); BOOST_TEST(boost::relaxed_get(v)); BOOST_TEST(boost::get(v)); BOOST_TEST(boost::strict_get(v)); BOOST_TEST(boost::relaxed_get(v)); if (ref_same) { BOOST_TEST(boost::get(v)); BOOST_TEST(boost::get(v)); BOOST_TEST(boost::strict_get(v)); BOOST_TEST(boost::strict_get(v)); BOOST_TEST(boost::relaxed_get(v)); BOOST_TEST(boost::relaxed_get(v)); } } else { BOOST_TEST(!boost::get(v)); BOOST_TEST(!boost::get(v)); BOOST_TEST(!boost::strict_get(v)); BOOST_TEST(!boost::strict_get(v)); BOOST_TEST(!boost::relaxed_get(v)); BOOST_TEST(!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_TEST(!boost::relaxed_get(v)); BOOST_TEST(!boost::relaxed_get(v)); BOOST_TEST(!boost::relaxed_get(v)); BOOST_TEST(!boost::relaxed_get(v)); BOOST_TEST(!boost::relaxed_get(v)); BOOST_TEST(!boost::relaxed_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); BOOST_TEST(!boost::polymorphic_relaxed_get(v)); BOOST_TEST(!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 bool is_ref = boost::is_lvalue_reference::value; (void)is_ref; if (!is_ref) { 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); check_get_on_types(&v); base b; var_ref_t v1(b); check_get_on_types(&v1); check_get_on_types(&v1); derived1 d1; var_ref_t v2(d1); check_get_on_types(&v2); check_get_on_types(&v2); derived2 d2; var_ref_t v3(d2); check_get_on_types(&v3); check_get_on_types(&v3); std::string s("Hello"); var_ref_t v4(s); check_get_on_types(&v4); check_get_on_types(&v4); } inline void get_cref_test() { int i = 0; var_cref_t v(i); BOOST_TEST(boost::get(&v)); BOOST_TEST(boost::get(&v)); BOOST_TEST(!boost::get(&v)); base b; var_cref_t v1(b); BOOST_TEST(boost::get(&v1)); BOOST_TEST(!boost::get(&v1)); BOOST_TEST(!boost::get(&v1)); std::string s("Hello"); const var_cref_t v4 = s; BOOST_TEST(boost::get(&v4)); BOOST_TEST(!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_TEST((holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element::value)); BOOST_TEST((!holds_element >::value)); BOOST_TEST((!holds_element >::value)); BOOST_TEST((!holds_element >::value)); BOOST_TEST((holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic::value)); BOOST_TEST((!holds_element_polymorphic >::value)); BOOST_TEST((!holds_element_polymorphic >::value)); BOOST_TEST((!holds_element_polymorphic >::value)); } inline void check_that_does_not_exist() { using namespace boost::detail::variant; BOOST_TEST((holds_element::value)); BOOST_TEST((holds_element::value)); BOOST_TEST((!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(); } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES class MoveonlyType { public: MoveonlyType() {} ~MoveonlyType() {} MoveonlyType(MoveonlyType&&) {} void operator=(MoveonlyType&&) {} private: MoveonlyType(const MoveonlyType&); void operator=(const MoveonlyType&); }; const boost::variant foo1() { return ""; } boost::variant foo2() { return ""; } inline void get_rvref_test() { boost::get(foo1()); boost::get(foo2()); boost::variant v; v = MoveonlyType(); boost::get(boost::move(v)); v = 3; v = MoveonlyType(); boost::get(v); boost::relaxed_get(boost::variant()); v = MoveonlyType(); MoveonlyType moved_from_variant(boost::get(boost::move(v))); } #endif // BOOST_NO_CXX11_RVALUE_REFERENCES int main() { get_test(); get_test_no_fallback(); get_ref_test(); get_cref_test(); get_recursive_test(); check_that_does_not_exist(); #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES get_rvref_test(); #endif return boost::report_errors(); }