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