417 lines
15 KiB
C++
417 lines
15 KiB
C++
//-----------------------------------------------------------------------------
|
|
// boost-libs variant/test/variant_get_test.cpp source file
|
|
// See http://www.boost.org for updates, documentation, and revision history.
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 2014-2017 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
|
|
#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/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<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_CHECK(boost::polymorphic_get<TestType>(v));
|
|
BOOST_CHECK(boost::polymorphic_get<const TestType>(v));
|
|
BOOST_CHECK(boost::polymorphic_strict_get<TestType>(v));
|
|
BOOST_CHECK(boost::polymorphic_strict_get<const TestType>(v));
|
|
BOOST_CHECK(boost::polymorphic_relaxed_get<TestType>(v));
|
|
BOOST_CHECK(boost::polymorphic_relaxed_get<const TestType>(v));
|
|
|
|
BOOST_CHECK(boost::polymorphic_get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_strict_get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_relaxed_get<cref_test_t>(v));
|
|
|
|
if (ref_same) {
|
|
BOOST_CHECK(boost::polymorphic_get<ref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_strict_get<ref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_strict_get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_relaxed_get<ref_test_t>(v));
|
|
BOOST_CHECK(boost::polymorphic_relaxed_get<cref_test_t>(v));
|
|
}
|
|
} else {
|
|
BOOST_CHECK(!boost::polymorphic_get<TestType>(v));
|
|
BOOST_CHECK(!boost::polymorphic_get<const TestType>(v));
|
|
BOOST_CHECK(!boost::polymorphic_strict_get<TestType>(v));
|
|
BOOST_CHECK(!boost::polymorphic_strict_get<const TestType>(v));
|
|
BOOST_CHECK(!boost::polymorphic_relaxed_get<TestType>(v));
|
|
BOOST_CHECK(!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_CHECK(boost::get<TestType>(v));
|
|
BOOST_CHECK(boost::get<const TestType>(v));
|
|
BOOST_CHECK(boost::strict_get<TestType>(v));
|
|
BOOST_CHECK(boost::strict_get<const TestType>(v));
|
|
BOOST_CHECK(boost::relaxed_get<TestType>(v));
|
|
BOOST_CHECK(boost::relaxed_get<const TestType>(v));
|
|
|
|
BOOST_CHECK(boost::get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::strict_get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::relaxed_get<cref_test_t>(v));
|
|
|
|
if (ref_same) {
|
|
BOOST_CHECK(boost::get<ref_test_t>(v));
|
|
BOOST_CHECK(boost::get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::strict_get<ref_test_t>(v));
|
|
BOOST_CHECK(boost::strict_get<cref_test_t>(v));
|
|
BOOST_CHECK(boost::relaxed_get<ref_test_t>(v));
|
|
BOOST_CHECK(boost::relaxed_get<cref_test_t>(v));
|
|
}
|
|
} else {
|
|
BOOST_CHECK(!boost::get<TestType>(v));
|
|
BOOST_CHECK(!boost::get<const TestType>(v));
|
|
BOOST_CHECK(!boost::strict_get<TestType>(v));
|
|
BOOST_CHECK(!boost::strict_get<const TestType>(v));
|
|
BOOST_CHECK(!boost::relaxed_get<TestType>(v));
|
|
BOOST_CHECK(!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_CHECK(!boost::relaxed_get<short>(v));
|
|
BOOST_CHECK(!boost::relaxed_get<const short>(v));
|
|
BOOST_CHECK(!boost::relaxed_get<char>(v));
|
|
BOOST_CHECK(!boost::relaxed_get<char*>(v));
|
|
BOOST_CHECK(!boost::relaxed_get<bool>(v));
|
|
BOOST_CHECK(!boost::relaxed_get<const bool>(v));
|
|
|
|
BOOST_CHECK(!boost::polymorphic_relaxed_get<short>(v));
|
|
BOOST_CHECK(!boost::polymorphic_relaxed_get<const short>(v));
|
|
BOOST_CHECK(!boost::polymorphic_relaxed_get<char>(v));
|
|
BOOST_CHECK(!boost::polymorphic_relaxed_get<char*>(v));
|
|
BOOST_CHECK(!boost::polymorphic_relaxed_get<bool>(v));
|
|
BOOST_CHECK(!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_CHECK(boost::get<const int>(&v));
|
|
BOOST_CHECK(boost::get<const int&>(&v));
|
|
BOOST_CHECK(!boost::get<const base>(&v));
|
|
|
|
base b;
|
|
var_cref_t v1(b);
|
|
BOOST_CHECK(boost::get<const base>(&v1));
|
|
BOOST_CHECK(!boost::get<const derived1>(&v1));
|
|
BOOST_CHECK(!boost::get<const int>(&v1));
|
|
|
|
std::string s("Hello");
|
|
const var_cref_t v4 = s;
|
|
BOOST_CHECK(boost::get<const std::string>(&v4));
|
|
BOOST_CHECK(!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_CHECK((holds_element<T, const int>::value));
|
|
BOOST_CHECK((!holds_element<T, short>::value));
|
|
BOOST_CHECK((!holds_element<T, short>::value));
|
|
BOOST_CHECK((!holds_element<T, const short>::value));
|
|
BOOST_CHECK((!holds_element<T, char*>::value));
|
|
BOOST_CHECK((!holds_element<T, const char*>::value));
|
|
BOOST_CHECK((!holds_element<T, char[5]>::value));
|
|
BOOST_CHECK((!holds_element<T, const char[5]>::value));
|
|
BOOST_CHECK((!holds_element<T, bool>::value));
|
|
BOOST_CHECK((!holds_element<T, const bool>::value));
|
|
|
|
BOOST_CHECK((!holds_element<T, boost::recursive_wrapper<int> >::value));
|
|
BOOST_CHECK((!holds_element<T, boost::recursive_wrapper<short> >::value));
|
|
BOOST_CHECK((!holds_element<T, boost::detail::reference_content<short> >::value));
|
|
|
|
|
|
BOOST_CHECK((holds_element_polymorphic<T, const int>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, short>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, short>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, const short>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, char*>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, const char*>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, char[5]>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, const char[5]>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, bool>::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, const bool>::value));
|
|
|
|
BOOST_CHECK((!holds_element_polymorphic<T, boost::recursive_wrapper<int> >::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, boost::recursive_wrapper<short> >::value));
|
|
BOOST_CHECK((!holds_element_polymorphic<T, boost::detail::reference_content<short> >::value));
|
|
}
|
|
|
|
inline void check_that_does_not_exist()
|
|
{
|
|
using namespace boost::detail::variant;
|
|
|
|
BOOST_CHECK((holds_element<var_t, int>::value));
|
|
BOOST_CHECK((holds_element<var_ref_t, int>::value));
|
|
BOOST_CHECK((!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 test_main(int , char* [])
|
|
{
|
|
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::exit_success;
|
|
}
|