[ create a new paste ] login | about

Link: http://codepad.org/zBOc3s25    [ raw code | output | fork ]

C++, pasted on Feb 24:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/parameter/keyword.hpp>

namespace boost {

// Some Boost.Parameter extension - this should really go to Boost.Parameter in the end
namespace parameter {

// The metafunction, given the type of the arguments pack and the keyword tag, returns the corresponding parameter type
template< typename ArgsT, typename KeywordTagT >
struct parameter_type
{
    typedef void type;
};

template< typename ArgT, typename KeywordTagT >
struct parameter_type< aux::tagged_argument< KeywordTagT, ArgT >, KeywordTagT >
{
    typedef typename aux::tagged_argument< KeywordTagT, ArgT >::value_type type;
};

template< typename KeywordTagT1, typename ArgT, typename KeywordTagT2 >
struct parameter_type< aux::tagged_argument< KeywordTagT1, ArgT >, KeywordTagT2 >
{
    typedef void type;
};

template< typename ArgT, typename TailT, typename KeywordTagT >
struct parameter_type<
    aux::arg_list<
        aux::tagged_argument< KeywordTagT, ArgT >,
        TailT
    >,
    KeywordTagT
>
{
    typedef typename aux::tagged_argument< KeywordTagT, ArgT >::value_type type;
};

template< typename KeywordTagT1, typename ArgT, typename TailT, typename KeywordTagT2 >
struct parameter_type<
    aux::arg_list<
        aux::tagged_argument< KeywordTagT1, ArgT >,
        TailT
    >,
    KeywordTagT2
> :
    public parameter_type< TailT, KeywordTagT2 >
{
};

} // namespace parameter


namespace conversion {

namespace keywords {

BOOST_PARAMETER_KEYWORD(tag, source)
BOOST_PARAMETER_KEYWORD(tag, default_)
BOOST_PARAMETER_KEYWORD(tag, radix)
BOOST_PARAMETER_KEYWORD(tag, bool_alpha)

} // namespace keywords

// Some traits to aid string-related conversion
template< typename T >
struct is_string : mpl::false_ {};

template< >
struct is_string< std::string > : mpl::true_ {};

// Conversion tags
struct string_to_integral_tag {};
struct integral_to_string_tag {};

template< typename FromT, typename ToT >
typename enable_if<
    mpl::and_<
        is_string< FromT >,
        is_integral< ToT >
    >,
    string_to_integral_tag
>::type get_conversion_tag(FromT*, ToT*);

template< typename FromT, typename ToT >
typename enable_if<
    mpl::and_<
        is_integral< FromT >,
        is_string< ToT >
    >,
    integral_to_string_tag
>::type get_conversion_tag(FromT*, ToT*);

template< typename FromT, typename ToT >
struct conversion_tag_of
{
    typedef BOOST_TYPEOF_TPL(get_conversion_tag((FromT*)0, (ToT*)0)) type;
};

// Converter functional object
template< typename ToT, typename ConversionTagT >
struct converter_impl;

template< typename FromT, typename ToT >
struct args_converter
{
    typedef ToT result_type;
    typedef typename conversion_tag_of< FromT, ToT >::type conversion_tag;

    template< typename ArgsT >
    result_type operator() (ArgsT const& args) const
    {
        converter_impl< ToT, conversion_tag > impl;
        return impl(args);
    }
    template< typename ArgsT >
    result_type operator() (FromT const& from, ArgsT const& args) const
    {
        converter_impl< ToT, conversion_tag > impl;
        return impl((args, keywords::source = from));
    }
};

template< typename FromT, typename ToT >
struct converter :
    public std::unary_function< FromT, ToT >
{
    typedef typename std::unary_function< FromT, ToT >::result_type result_type;
    typedef typename conversion_tag_of< FromT, ToT >::type conversion_tag;

private:
    boost::function1< result_type, FromT const& > m_Converter;

public:
    template< typename ArgsT >
    explicit converter(ArgsT const& args) : m_Converter(boost::bind(args_converter< FromT, ToT >(), _1, args))
    {
    }

    result_type operator() (FromT const& from) const
    {
        return m_Converter(from);
    }
};

// This function should be declared with Boost.Parameter macros
template< typename ToT, typename ArgsT >
inline ToT convert(ArgsT const& args)
{
    typedef typename parameter::parameter_type< ArgsT, keywords::tag::source >::type from_type;
    args_converter< from_type, ToT > conv;
    return conv(args);
}

// String-to-integral conversion
template< typename ToT >
struct converter_impl< ToT, string_to_integral_tag >
{
    typedef ToT result_type;

    template< typename ArgsT >
    ToT operator() (ArgsT const& args) const
    {
        std::istringstream strm(args[keywords::source]);

        if (args[keywords::bool_alpha | false])
        {
            strm >> std::boolalpha;
        }

        switch (args[keywords::radix | 10])
        {
        case 16:
            strm >> std::hex; break;
        case 8:
            strm >> std::oct; break;
        }

        ToT result = args[keywords::default_];
        strm >> result;

        return result;
    }
};

// Integral-to-string conversion
template< typename ToT >
struct converter_impl< ToT, integral_to_string_tag >
{
    typedef ToT result_type;

    template< typename ArgsT >
    ToT operator() (ArgsT const& args) const
    {
        std::ostringstream strm;

        if (args[keywords::bool_alpha | false])
        {
            strm << std::boolalpha;
        }

        switch (args[keywords::radix | 10])
        {
        case 16:
            strm << std::hex; break;
        case 8:
            strm << std::oct; break;
        }

        strm << args[keywords::source];

        if (strm.good())
            return strm.str();
        else
            return args[keywords::default_];
    }
};

} // namespace conversion

} // namespace boost

namespace
user
	{
	struct
	uuid
		{
		unsigned char value_[16];
		};
	}

namespace
boost
	{
	namespace
	conversion
		{
		struct uuid_to_string_tag {};

		template <typename ToT>
		typename
			enable_if<
				is_string< ToT >,
				uuid_to_string_tag >::type
		get_conversion_tag( user::uuid*, ToT* );

		template <>
		struct
		converter_impl<user::uuid,uuid_to_string_tag>
			{
			typedef std::string result_type;

			result_type
			operator()() const
				{
				return std::string("Test");
				}
			};
		}
	}

int main(int, char*[])
{
    using namespace boost::conversion;

    // After utilizing Boost.Parameter macros the double parenthesis will not be needed,
    // and the "source" parameter will be able to be specified without the "source" keyword.
    std::string s = convert< std::string >((
        keywords::source = 100,
        keywords::radix = 16,
        keywords::default_ = "[error]"));

    int n = convert< int >((
        keywords::source = s,
        keywords::radix = 16,
        keywords::default_ = -1));

    std::cout << "s = '" << s << "', n = " << n << std::endl;

    boost::array< int, 5 > ints = { 10, 20, 30, 40, 50 };

    std::vector< std::string > strings;
    std::transform(ints.begin(), ints.end(), std::back_inserter(strings),
        converter< int, std::string >((keywords::radix = 16, keywords::default_ = "[error]")));

    std::copy(strings.begin(), strings.end(), std::ostream_iterator< std::string >(std::cout, ", "));

    std::cout << std::endl;

	user::uuid u;
	std::cout << convert<std::string>((keywords::source=u));
    return 0;
}


Output:
1
2
3
4
5
6
7
8
9
10
cc1plus: warnings being treated as errors
In function 'int main(int, char**)':
Line 296: warning: missing braces around initializer for 'int [5]'
t.cpp: At global scope:
t.cpp: In instantiation of 'boost::conversion::conversion_tag_of<user::uuid, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >':
t.cpp:124:   instantiated from 'boost::conversion::args_converter<user::uuid, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
t.cpp:167:   instantiated from 'ToT boost::conversion::convert(const ArgsT&) [with ToT = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, ArgsT = boost::parameter::aux::tagged_argument<boost::conversion::keywords::tag::source, user::uuid>]'
t.cpp:308:   instantiated from here
Line 112: error: no matching function for call to 'get_conversion_tag(user::uuid*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
compilation terminated due to -Wfatal-errors.


Create a new paste based on this one


Comments: