123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- //-----------------------------------------------------------------------------
- // 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<int, base, derived1, derived2, std::string> var_t;
- typedef boost::variant<int, derived1, derived2, std::string> var_t_shortened;
- typedef boost::variant<base, derived1, derived2> var_t_no_fallback;
- typedef boost::variant<int&, base&, derived1&, derived2&, std::string&> var_ref_t;
- typedef boost::variant<const int&, const base&, const derived1&, const derived2&, const std::string&> var_cref_t;
- struct recursive_structure;
- typedef boost::variant<
- int, base, derived1, derived2, std::string, boost::recursive_wrapper<recursive_structure>
- > var_req_t;
- struct recursive_structure { var_req_t var; };
- template <class TypeInVariant, class V, class TestType>
- inline void check_polymorphic_get_on_types_impl_single_type(V* v)
- {
- typedef typename boost::add_reference<TestType>::type ref_test_t;
- typedef typename boost::add_reference<const TestType>::type cref_test_t;
- const bool exact_same = !!boost::is_same<TypeInVariant, TestType>::value;
- const bool ref_same = !!boost::is_same<TypeInVariant, ref_test_t>::value;
- if (exact_same || ref_same) {
- BOOST_TEST(boost::polymorphic_get<TestType>(v));
- BOOST_TEST(boost::polymorphic_get<const TestType>(v));
- BOOST_TEST(boost::polymorphic_strict_get<TestType>(v));
- BOOST_TEST(boost::polymorphic_strict_get<const TestType>(v));
- BOOST_TEST(boost::polymorphic_relaxed_get<TestType>(v));
- BOOST_TEST(boost::polymorphic_relaxed_get<const TestType>(v));
- BOOST_TEST(boost::polymorphic_get<cref_test_t>(v));
- BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v));
- BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v));
- if (ref_same) {
- BOOST_TEST(boost::polymorphic_get<ref_test_t>(v));
- BOOST_TEST(boost::polymorphic_get<cref_test_t>(v));
- BOOST_TEST(boost::polymorphic_strict_get<ref_test_t>(v));
- BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v));
- BOOST_TEST(boost::polymorphic_relaxed_get<ref_test_t>(v));
- BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v));
- }
- } else {
- BOOST_TEST(!boost::polymorphic_get<TestType>(v));
- BOOST_TEST(!boost::polymorphic_get<const TestType>(v));
- BOOST_TEST(!boost::polymorphic_strict_get<TestType>(v));
- BOOST_TEST(!boost::polymorphic_strict_get<const TestType>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<TestType>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<const TestType>(v));
- }
- }
- template <class T, class V, class TestType>
- inline void check_get_on_types_impl_single_type(V* v)
- {
- typedef typename boost::add_reference<TestType>::type ref_test_t;
- typedef typename boost::add_reference<const TestType>::type cref_test_t;
- const bool exact_same = !!boost::is_same<T, TestType>::value;
- const bool ref_same = !!boost::is_same<T, ref_test_t>::value;
- if (exact_same || ref_same) {
- BOOST_TEST(boost::get<TestType>(v));
- BOOST_TEST(boost::get<const TestType>(v));
- BOOST_TEST(boost::strict_get<TestType>(v));
- BOOST_TEST(boost::strict_get<const TestType>(v));
- BOOST_TEST(boost::relaxed_get<TestType>(v));
- BOOST_TEST(boost::relaxed_get<const TestType>(v));
- BOOST_TEST(boost::get<cref_test_t>(v));
- BOOST_TEST(boost::strict_get<cref_test_t>(v));
- BOOST_TEST(boost::relaxed_get<cref_test_t>(v));
- if (ref_same) {
- BOOST_TEST(boost::get<ref_test_t>(v));
- BOOST_TEST(boost::get<cref_test_t>(v));
- BOOST_TEST(boost::strict_get<ref_test_t>(v));
- BOOST_TEST(boost::strict_get<cref_test_t>(v));
- BOOST_TEST(boost::relaxed_get<ref_test_t>(v));
- BOOST_TEST(boost::relaxed_get<cref_test_t>(v));
- }
- } else {
- BOOST_TEST(!boost::get<TestType>(v));
- BOOST_TEST(!boost::get<const TestType>(v));
- BOOST_TEST(!boost::strict_get<TestType>(v));
- BOOST_TEST(!boost::strict_get<const TestType>(v));
- BOOST_TEST(!boost::relaxed_get<TestType>(v));
- BOOST_TEST(!boost::relaxed_get<const TestType>(v));
- }
- }
- template <class T, class V>
- inline void check_get_on_types_impl(V* v)
- {
- check_get_on_types_impl_single_type<T, V, int>(v);
- check_polymorphic_get_on_types_impl_single_type<T, V, int>(v);
- check_get_on_types_impl_single_type<T, V, base>(v);
- check_get_on_types_impl_single_type<T, V, derived1>(v);
- check_polymorphic_get_on_types_impl_single_type<T, V, derived1>(v);
- check_get_on_types_impl_single_type<T, V, derived2>(v);
- check_polymorphic_get_on_types_impl_single_type<T, V, derived2>(v);
- check_get_on_types_impl_single_type<T, V, std::string>(v);
- check_polymorphic_get_on_types_impl_single_type<T, V, std::string>(v);
- // Never exist in here
- BOOST_TEST(!boost::relaxed_get<short>(v));
- BOOST_TEST(!boost::relaxed_get<const short>(v));
- BOOST_TEST(!boost::relaxed_get<char>(v));
- BOOST_TEST(!boost::relaxed_get<char*>(v));
- BOOST_TEST(!boost::relaxed_get<bool>(v));
- BOOST_TEST(!boost::relaxed_get<const bool>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<short>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<const short>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<char>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<char*>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<bool>(v));
- BOOST_TEST(!boost::polymorphic_relaxed_get<const bool>(v));
- boost::get<T>(*v); // Must compile
- boost::get<const T>(*v); // Must compile
- boost::strict_get<T>(*v); // Must compile
- boost::strict_get<const T>(*v); // Must compile
- bool is_ref = boost::is_lvalue_reference<T>::value;
- (void)is_ref;
- if (!is_ref) {
- boost::polymorphic_get<T>(*v); // Must compile
- boost::polymorphic_get<const T>(*v); // Must compile
- boost::polymorphic_strict_get<T>(*v); // Must compile
- boost::polymorphic_strict_get<const T>(*v); // Must compile
- }
- }
- template <class T, class V>
- inline void check_get_on_types(V* v)
- {
- check_get_on_types_impl<T, V>(v);
- check_get_on_types_impl<T, const V>(v);
- }
- inline void get_test()
- {
- var_t v;
- check_get_on_types<int>(&v);
- var_t(base()).swap(v);
- check_get_on_types<base>(&v);
- var_t(derived1()).swap(v);
- check_get_on_types<derived1>(&v);
- var_t(derived2()).swap(v);
- check_get_on_types<derived2>(&v);
- var_t(std::string("Hello")).swap(v);
- check_get_on_types<std::string>(&v);
- var_t_shortened vs = derived2();
- check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs);
- check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs);
- // Checking that Base is really determinated
- check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs);
- check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs);
- vs = derived1();
- check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs);
- check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs);
- // Checking that Base is really determinated
- check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs);
- check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&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<base, var_t_no_fallback, base>(&v);
- check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
- check_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
- check_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
- var_t_no_fallback(derived1()).swap(v);
- check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
- check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
- check_get_on_types_impl_single_type<derived1, var_t_no_fallback, derived1>(&v);
- check_get_on_types_impl_single_type<derived1, const var_t_no_fallback, derived1>(&v);
- var_t_no_fallback(derived2()).swap(v);
- check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
- check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
- check_get_on_types_impl_single_type<derived2, var_t_no_fallback, derived2>(&v);
- check_get_on_types_impl_single_type<derived2, const var_t_no_fallback, derived2>(&v);
- }
- inline void get_ref_test()
- {
- int i = 0;
- var_ref_t v(i);
- check_get_on_types<int>(&v);
- check_get_on_types<int&>(&v);
- base b;
- var_ref_t v1(b);
- check_get_on_types<base>(&v1);
- check_get_on_types<base&>(&v1);
- derived1 d1;
- var_ref_t v2(d1);
- check_get_on_types<derived1>(&v2);
- check_get_on_types<derived1&>(&v2);
- derived2 d2;
- var_ref_t v3(d2);
- check_get_on_types<derived2>(&v3);
- check_get_on_types<derived2&>(&v3);
- std::string s("Hello");
- var_ref_t v4(s);
- check_get_on_types<std::string>(&v4);
- check_get_on_types<std::string&>(&v4);
- }
- inline void get_cref_test()
- {
- int i = 0;
- var_cref_t v(i);
- BOOST_TEST(boost::get<const int>(&v));
- BOOST_TEST(boost::get<const int&>(&v));
- BOOST_TEST(!boost::get<const base>(&v));
- base b;
- var_cref_t v1(b);
- BOOST_TEST(boost::get<const base>(&v1));
- BOOST_TEST(!boost::get<const derived1>(&v1));
- BOOST_TEST(!boost::get<const int>(&v1));
- std::string s("Hello");
- const var_cref_t v4 = s;
- BOOST_TEST(boost::get<const std::string>(&v4));
- BOOST_TEST(!boost::get<const int>(&v4));
- }
- inline void get_recursive_test()
- {
- var_req_t v;
- check_get_on_types<int>(&v);
- var_req_t(base()).swap(v);
- check_get_on_types<base>(&v);
- var_req_t(derived1()).swap(v);
- check_get_on_types<derived1>(&v);
- var_req_t(derived2()).swap(v);
- check_get_on_types<derived2>(&v);
- var_req_t(std::string("Hello")).swap(v);
- check_get_on_types<std::string>(&v);
- recursive_structure s = { v }; // copying "v"
- v = s;
- check_get_on_types<recursive_structure>(&v);
- }
- template <class T>
- inline void check_that_does_not_exist_impl()
- {
- using namespace boost::detail::variant;
- BOOST_TEST((holds_element<T, const int>::value));
- BOOST_TEST((!holds_element<T, short>::value));
- BOOST_TEST((!holds_element<T, short>::value));
- BOOST_TEST((!holds_element<T, const short>::value));
- BOOST_TEST((!holds_element<T, char*>::value));
- BOOST_TEST((!holds_element<T, const char*>::value));
- BOOST_TEST((!holds_element<T, char[5]>::value));
- BOOST_TEST((!holds_element<T, const char[5]>::value));
- BOOST_TEST((!holds_element<T, bool>::value));
- BOOST_TEST((!holds_element<T, const bool>::value));
- BOOST_TEST((!holds_element<T, boost::recursive_wrapper<int> >::value));
- BOOST_TEST((!holds_element<T, boost::recursive_wrapper<short> >::value));
- BOOST_TEST((!holds_element<T, boost::detail::reference_content<short> >::value));
- BOOST_TEST((holds_element_polymorphic<T, const int>::value));
- BOOST_TEST((!holds_element_polymorphic<T, short>::value));
- BOOST_TEST((!holds_element_polymorphic<T, short>::value));
- BOOST_TEST((!holds_element_polymorphic<T, const short>::value));
- BOOST_TEST((!holds_element_polymorphic<T, char*>::value));
- BOOST_TEST((!holds_element_polymorphic<T, const char*>::value));
- BOOST_TEST((!holds_element_polymorphic<T, char[5]>::value));
- BOOST_TEST((!holds_element_polymorphic<T, const char[5]>::value));
- BOOST_TEST((!holds_element_polymorphic<T, bool>::value));
- BOOST_TEST((!holds_element_polymorphic<T, const bool>::value));
- BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<int> >::value));
- BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<short> >::value));
- BOOST_TEST((!holds_element_polymorphic<T, boost::detail::reference_content<short> >::value));
- }
- inline void check_that_does_not_exist()
- {
- using namespace boost::detail::variant;
- BOOST_TEST((holds_element<var_t, int>::value));
- BOOST_TEST((holds_element<var_ref_t, int>::value));
- BOOST_TEST((!holds_element<var_cref_t, int>::value));
- check_that_does_not_exist_impl<var_t>();
- check_that_does_not_exist_impl<var_ref_t>();
- check_that_does_not_exist_impl<var_cref_t>();
- check_that_does_not_exist_impl<var_req_t>();
- }
- #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<int, std::string> foo1() { return ""; }
- boost::variant<int, std::string> foo2() { return ""; }
- inline void get_rvref_test()
- {
- boost::get<std::string>(foo1());
- boost::get<std::string>(foo2());
- boost::variant<MoveonlyType, int> v;
- v = MoveonlyType();
- boost::get<MoveonlyType>(boost::move(v));
- v = 3;
- v = MoveonlyType();
- boost::get<MoveonlyType>(v);
- boost::relaxed_get<MoveonlyType&>(boost::variant<MoveonlyType, int>());
- v = MoveonlyType();
- MoveonlyType moved_from_variant(boost::get<MoveonlyType>(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();
- }
|