#include <cstddef>
#include <cstdio>
#include <fstream>
#include <boost/config.hpp>
#if BOOST_CXX_VERSION > 199711L
#include <boost/math/special_functions/next.hpp>
#endif
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std {
using ::remove;
}
#endif
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#if defined(_MSC_VER) && (_MSC_VER <= 1020)
# pragma warning (disable : 4786)
#endif
#include "test_tools.hpp"
#include <boost/archive/archive_exception.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/throw_exception.hpp>
#include <boost/variant/static_visitor.hpp>
namespace boost {
template<typename ResultType> class static_visitor;
}
#include "A.hpp"
#include "A.ipp"
class are_equal
: public boost::static_visitor<bool>
{
public:
typedef bool result_type;
struct same {
template<class T, class U>
static bool invoke(const T & t, const U & u){
return t == u;
}
};
struct not_same {
template<class T, class U>
static bool invoke(const T &, const U &){
return false;
}
};
template <class T, class U>
bool operator()( const T & t, const U & u) const
{
typedef typename boost::mpl::eval_if<boost::is_same<T, U>,
boost::mpl::identity<same>,
boost::mpl::identity<not_same>
>::type type;
return type::invoke(t, u);
}
template <class T, class U>
bool operator()(T * const & t, U * const & u) const
{
return this->operator()(*t, *u);
}
bool operator()( const float & lhs, const float & rhs ) const
{
#if BOOST_CXX_VERSION > 199711L
return std::abs( boost::math::float_distance(lhs, rhs) ) < 2;
#else
return true;
#endif
}
bool operator()( const double & lhs, const double & rhs ) const
{
#if BOOST_CXX_VERSION > 199711L
return std::abs( boost::math::float_distance(lhs, rhs) ) < 2;
#else
return true;
#endif
}
};
template<class Variant>
bool test_type(const Variant & v){
const char * testfile = boost::archive::tmpnam(NULL);
BOOST_REQUIRE(testfile != NULL);
{
test_ostream os(testfile, TEST_STREAM_FLAGS);
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
oa << boost::serialization::make_nvp("written", v);
}
Variant vx;
{
test_istream is(testfile, TEST_STREAM_FLAGS);
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
BOOST_TRY {
ia >> boost::serialization::make_nvp("written", vx);
BOOST_CHECK(visit(are_equal(), v, vx));
}
BOOST_CATCH(boost::archive::archive_exception const& e) {
return false;
}
BOOST_CATCH_END
}
std::remove(testfile);
return true;
}
template<class Variant>
void test(Variant & v)
{
test_type(v);
v = false;
test_type(v);
v = 1;
test_type(v);
v = (float) 2.3;
test_type(v);
v = (double) 6.4;
test_type(v);
v = A();
test_type(v);
v = std::string("we can't stop here, this is Bat Country");
test_type(v);
}
#include <boost/serialization/variant.hpp>
#include <boost/variant/variant.hpp>
#include <cstdio>
int test_boost_variant(){
std::cerr << "Testing boost_variant\n";
boost::variant<bool, int, float, double, A, std::string> v;
test(v);
const A a;
boost::variant<bool, int, float, double, const A *, std::string> v1 = & a;
test_type(v1);
return EXIT_SUCCESS;
}
#if BOOST_CXX_VERSION >= 201103L
#include <boost/variant2/variant.hpp>
int test_boost_variant2(){
std::cerr << "Testing boost_variant2\n";
boost::variant2::variant<bool, int, float, double, A, std::string> v;
test(v);
const A a;
boost::variant2::variant<bool, int, float, double, const A *, std::string> v1 = & a;
test_type(v1);
return EXIT_SUCCESS;
}
#endif
#ifndef BOOST_NO_CXX17_HDR_VARIANT
#include <variant>
int test_std_variant(){
std::cerr << "Testing Std Variant\n";
std::variant<bool, int, float, double, A, std::string> v;
test(v);
const A a;
std::variant<bool, int, float, double, const A *, std::string> v1 = & a;
test_type(v1);
return EXIT_SUCCESS;
}
#endif
int test_main( int , char* [] ){
return test_boost_variant()
#if BOOST_CXX_VERSION >= 201103L
|| test_boost_variant2()
#endif
#ifndef BOOST_NO_CXX17_HDR_VARIANT
|| test_std_variant()
#endif
;
}