336 lines
6.5 KiB
C++
Executable File
336 lines
6.5 KiB
C++
Executable File
//-----------------------------------------------------------------------------
|
|
// 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/type_index.hpp"
|
|
#include "boost/detail/workaround.hpp"
|
|
#if BOOST_WORKAROUND(BOOST_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_TEST(boost::apply_visitor(total_sizeof(), cvar) == sizeof(S));
|
|
BOOST_TEST(cvar.type() == boost::typeindex::type_id<S>());
|
|
|
|
//
|
|
// Check get<>()
|
|
//
|
|
BOOST_TEST(boost::get<S>(&var));
|
|
BOOST_TEST(boost::get<S>(&cvar));
|
|
|
|
const S* ptr1 = 0;
|
|
const S* ptr2 = 0;
|
|
try
|
|
{
|
|
S& r = boost::get<S>(var);
|
|
ptr1 = &r;
|
|
}
|
|
catch(const boost::bad_get& )
|
|
{
|
|
BOOST_ERROR( "get<S> failed unexpectedly" );
|
|
}
|
|
|
|
try
|
|
{
|
|
const S& cr = boost::get<S>(cvar);
|
|
ptr2 = &cr;
|
|
}
|
|
catch(const boost::bad_get& )
|
|
{
|
|
BOOST_ERROR( "get<S> const failed unexpectedly" );
|
|
}
|
|
|
|
BOOST_TEST(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_TEST(temp == str);
|
|
}
|
|
}
|
|
|
|
|
|
template<typename VariantType, typename S>
|
|
inline void verify_not(VariantType& var, spec<S>)
|
|
{
|
|
const VariantType& cvar = var;
|
|
|
|
BOOST_TEST(cvar.type() != boost::typeindex::type_id<S>());
|
|
|
|
//
|
|
// Check get<>()
|
|
//
|
|
BOOST_TEST(!boost::get<S>(&var));
|
|
BOOST_TEST(!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(const 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(const boost::bad_get& )
|
|
{
|
|
// do nothing except pass-through
|
|
}
|
|
|
|
BOOST_TEST(ptr1 == 0 && ptr2 == 0);
|
|
}
|
|
|
|
|
|
#endif //_JOBSH_INC_
|