variant/test/variant_get_test.cpp

214 lines
6.5 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 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/variant.hpp"
#include "boost/variant/get.hpp"
#include "boost/variant/recursive_wrapper.hpp"
#include "boost/test/minimal.hpp"
struct base {int trash;};
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&, 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 T, class V, class TestType>
inline void check_get_on_types_impl_single_type(V* v)
{
if (!!boost::is_same<T, TestType>::value) {
BOOST_CHECK(boost::get<TestType>(v));
BOOST_CHECK(boost::get<const TestType>(v));
BOOST_CHECK(boost::safe_get<TestType>(v));
BOOST_CHECK(boost::safe_get<const TestType>(v));
BOOST_CHECK(boost::unsafe_get<TestType>(v));
BOOST_CHECK(boost::unsafe_get<const TestType>(v));
} else {
BOOST_CHECK(!boost::get<TestType>(v));
BOOST_CHECK(!boost::get<const TestType>(v));
BOOST_CHECK(!boost::safe_get<TestType>(v));
BOOST_CHECK(!boost::safe_get<const TestType>(v));
BOOST_CHECK(!boost::unsafe_get<TestType>(v));
BOOST_CHECK(!boost::unsafe_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_get_on_types_impl_single_type<T, V, base>(v);
check_get_on_types_impl_single_type<T, V, derived1>(v);
check_get_on_types_impl_single_type<T, V, derived2>(v);
check_get_on_types_impl_single_type<T, V, std::string>(v);
// Never exist in here
BOOST_CHECK(!boost::unsafe_get<short>(v));
BOOST_CHECK(!boost::unsafe_get<const short>(v));
BOOST_CHECK(!boost::unsafe_get<char>(v));
BOOST_CHECK(!boost::unsafe_get<char*>(v));
BOOST_CHECK(!boost::unsafe_get<bool>(v));
BOOST_CHECK(!boost::unsafe_get<const bool>(v));
boost::get<T>(*v); // Must compile
boost::get<const T>(*v); // Must compile
boost::safe_get<T>(*v); // Must compile
boost::safe_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);
}
inline void get_ref_test()
{
int i = 0;
var_ref_t v(i);
check_get_on_types<int>(&v);
base b;
var_ref_t v1(b);
check_get_on_types<base>(&v1);
derived1 d1;
var_ref_t v2(d1);
check_get_on_types<derived1>(&v2);
derived2 d2;
var_ref_t v3(d2);
check_get_on_types<derived2>(&v3);
std::string s("Hello");
var_ref_t v4(s);
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 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[]>::value));
BOOST_CHECK((!holds_element<T, const char[]>::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));
}
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>();
}
int test_main(int , char* [])
{
get_test();
get_ref_test();
get_cref_test();
get_recursive_test();
check_that_does_not_exist();
return boost::exit_success;
}