blob: ffba05e625fad09d9bc205c2ee151eeea5e03b59 [file] [log] [blame]
//-----------------------------------------------------------------------------
// boost-libs variant/libs/test/jobs.h header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// 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)
#ifndef _JOBSH_INC_
#define _JOBSH_INC_
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>
#include <vector>
#include "boost/variant/variant_fwd.hpp"
#include "boost/variant/get.hpp"
#include "boost/variant/apply_visitor.hpp"
#include "boost/variant/static_visitor.hpp"
#include "boost/detail/workaround.hpp"
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
# pragma warn -lvc
#endif
struct to_text : boost::static_visitor<std::string>
{
private: // NO_FUNCTION_TEMPLATE_ORDERING workaround
template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
std::string to_text_impl(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) >& operand, long
) const
{
std::ostringstream ost;
ost << "[V] " << boost::apply_visitor(to_text(), operand);
return ost.str();
}
template <typename Value>
std::string to_text_impl(const Value& operand, int) const
{
std::ostringstream ost;
ost << "[V] " << operand;
return ost.str();
}
public:
template <typename T>
std::string operator()(const T& operand) const
{
return to_text_impl(operand, 1L);
}
};
struct total_sizeof : boost::static_visitor<int>
{
total_sizeof() : total_(0) { }
template<class Value>
int operator()(const Value&) const
{
total_ += sizeof(Value);
return total_;
}
int result() const
{
return total_;
}
mutable int total_;
}; // total_sizeof
//Function object: sum_int
//Description: Compute total sum of a series of numbers, (when called successively)
//Use sizeof(T) if applied with a non-integral type
struct sum_int : boost::static_visitor<int>
{
sum_int() : total_(0) { }
template<int n>
struct int_to_type
{
BOOST_STATIC_CONSTANT(int, value = n);
};
//Integral type - add numerical value
template<typename T>
void add(T t, int_to_type<true> ) const
{
total_ += t;
}
//Other types - add sizeof<T>
template<typename T>
void add(T& , int_to_type<false> ) const
{
total_ += sizeof(T);
}
template<typename T>
int operator()(const T& t) const
{
//Int_to_type is used to select the correct add() overload
add(t, int_to_type<boost::is_integral<T>::value>());
return total_;
}
int result() const
{
return total_;
}
private:
mutable int total_;
}; //sum_int
//Function object: sum_double
//Description: Compute total sum of a series of numbers, (when called successively)
//Accpetable input types: float, double (Other types are silently ignored)
struct sum_double : boost::static_visitor<double>
{
sum_double() : total_(0) { }
void operator()(float value) const
{
total_ += value;
}
void operator()(double value) const
{
total_ += value;
}
template<typename T>
void operator()(const T&) const
{
//Do nothing
}
double result() const
{
return total_;
}
private:
mutable double total_;
}; //sum_double
struct int_printer : boost::static_visitor<std::string>
{
int_printer(std::string prefix_s = "") : prefix_s_(prefix_s) { }
int_printer(const int_printer& other) : prefix_s_(other.prefix_s_)
{
ost_ << other.str();
}
std::string operator()(int x) const
{
ost_ << prefix_s_ << x;
return str();
}
std::string operator()(const std::vector<int>& x) const
{
ost_ << prefix_s_;
//Use another Int_printer object for printing a list of all integers
int_printer job(",");
ost_ << std::for_each(x.begin(), x.end(), job).str();
return str();
}
std::string str() const
{
return ost_.str();
}
private:
std::string prefix_s_;
mutable std::ostringstream ost_;
}; //int_printer
struct int_adder : boost::static_visitor<>
{
int_adder(int rhs) : rhs_(rhs) { }
result_type operator()(int& lhs) const
{
lhs += rhs_;
}
template<typename T>
result_type operator()(const T& ) const
{
//Do nothing
}
int rhs_;
}; //int_adder
template<typename T>
struct spec
{
typedef T result;
};
template<typename VariantType, typename S>
inline void verify(VariantType& var, spec<S>, std::string str = "")
{
const VariantType& cvar = var;
BOOST_CHECK(boost::apply_visitor(total_sizeof(), cvar) == sizeof(S));
#if !defined(BOOST_NO_TYPEID)
BOOST_CHECK(cvar.type() == typeid(S));
#endif
//
// Check get<>()
//
BOOST_CHECK(boost::get<S>(&var));
BOOST_CHECK(boost::get<S>(&cvar));
const S* ptr1 = 0;
const S* ptr2 = 0;
try
{
S& r = boost::get<S>(var);
ptr1 = &r;
}
catch(boost::bad_get& )
{
BOOST_ERROR( "get<S> failed unexpectedly" );
}
try
{
const S& cr = boost::get<S>(cvar);
ptr2 = &cr;
}
catch(boost::bad_get& )
{
BOOST_ERROR( "get<S> const failed unexpectedly" );
}
BOOST_CHECK(ptr1 != 0 && ptr2 == ptr1);
//
// Check string content
//
if(str.length() > 0)
{
std::string temp = boost::apply_visitor(to_text(), cvar);
std::cout << "temp = " << temp << ", str = " << str << std::endl;
BOOST_CHECK(temp == str);
}
}
template<typename VariantType, typename S>
inline void verify_not(VariantType& var, spec<S>)
{
const VariantType& cvar = var;
#if !defined(BOOST_NO_TYPEID)
BOOST_CHECK(cvar.type() != typeid(S));
#endif
//
// Check get<>()
//
BOOST_CHECK(!boost::get<S>(&var));
BOOST_CHECK(!boost::get<S>(&cvar));
const S* ptr1 = 0;
const S* ptr2 = 0;
try
{
S& r = boost::get<S>(var); // should throw
BOOST_ERROR( "get<S> passed unexpectedly" );
ptr1 = &r;
}
catch(boost::bad_get& )
{
// do nothing except pass-through
}
try
{
const S& cr = boost::get<S>(var); // should throw
BOOST_ERROR( "get<S> const passed unexpectedly" );
ptr2 = &cr;
}
catch(boost::bad_get& )
{
// do nothing except pass-through
}
BOOST_CHECK(ptr1 == 0 && ptr2 == 0);
}
#endif //_JOBSH_INC_