Boost logo

Boost Users :

From: Markus Werle (numerical.simulation_at_[hidden])
Date: 2008-08-20 10:35:40


> [ignore this gmane cheater line]

Hi!

Looks like migration from boost::tuple to std::tr1:.tuple is a lot
more pain than I thought.
I have some compile time magic class that makes use of the default
template args of boost::tuple:

template <
        typename T0 = boost::tuples::null_type,
        typename T1 = boost::tuples::null_type,
        typename T2 = boost::tuples::null_type,
        typename T3 = boost::tuples::null_type,
        typename T4 = boost::tuples::null_type,
        typename T5 = boost::tuples::null_type,
        typename T6 = boost::tuples::null_type,
        typename T7 = boost::tuples::null_type,
        typename T8 = boost::tuples::null_type,
        typename T9 = boost::tuples::null_type>
struct string_to_tuple
{
  // ...
};

Now from the docs I see:

namespace std {
namespace tr1 {

// [6.1.3] Class template tuple
template <class T1 = unspecified ,
class T2 = unspecified ,
...,
class TM = unspecified > class tuple;

which leaves me lost without typeof(std::tr1::ignore) at hand.
Any idea how to get around this?

Btw.: Why does the standard leave this type unspecified?

To be more specific: rewrite this code based on std::tr1::tuple ;-)

--- snip ---
// Usage:
// int main()
// {
// try
// {
// {
// typedef boost::tuple<int, int> tuple_t;
//
// std::list<tuple_t> test =
// string_to_tuple<int, int>::apply(" ( 1, 2 )
( 3, 4)(5,6)");
//
// std::copy(test.begin(), test.end(),
// std::ostream_iterator<tuple_t>
(std::cout, "\n"));
// }
//
// {
// typedef boost::tuple<unsigned int, int, double> tuple_t;
//
// std::list<tuple_t> test =
// string_to_tuple<unsigned int, int,
double>::apply
// (" ( 1, -2 , 5.123) ( 3, 4,7.9)(5,6,8.6789)");
//
// std::copy(test.begin(), test.end(),
// std::ostream_iterator<tuple_t>
(std::cout, "\n"));
// }
//
// }
// catch (std::exception const & e)
// {
// std::cerr << e.what() << std::endl;
// }
// }

#ifndef BOOSTTUPLESFROMSTRING_H
#define BOOSTTUPLESFROMSTRING_H

// #define BOOST_SPIRIT_DEBUG_OUT std::cerr
// #define BOOST_SPIRIT_DEBUG

#include "Enforce.h"

#ifndef PHOENIX_LIMIT
  #define PHOENIX_LIMIT 11
#else
  #if (PHOENIX_LIMIT < 11)
    #define ERROR_MESSAGE LOCATION ": " \
    "PHOENIX_LIMIT must be a at least 11, but is " \
    STRINGIZE(PHOENIX_LIMIT)
    #pragma message (ERROR_MESSAGE)
    #error Check the output for details
  #endif
#endif

#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
#include <boost/spirit/core.hpp>
#include <boost/spirit/attribute.hpp>
#include <boost/spirit/core/non_terminal/rule.hpp>
#include <boost/spirit/utility/lists.hpp>
#include <boost/spirit/utility/loops.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <boost/spirit/actor/push_back_actor.hpp>
#include <boost/spirit/actor/assign_actor.hpp>
#include <boost/spirit/phoenix/primitives.hpp>
#include <boost/spirit/phoenix/functions.hpp>

#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>

#include <list>
#include <iterator>
#include <algorithm>
#include <string>

namespace boost
{
namespace spirit
{

struct no_action
{
        template<
                typename T,
                typename ValueT
>
        void act(T& ref_, ValueT const& value_) const
        {
                // do nothing
        }
        template<
                typename T,
                typename IteratorT
>
        void act(
                T& ref_,
                IteratorT const& first_,
                IteratorT const& last_
                ) const
        {
                // do nothing
        }
};

static inline
boost::spirit::ref_value_actor<boost::tuples::null_type, no_action>
assign_a(boost::tuples::null_type & nt)
{
        boost::spirit::ref_value_actor<boost::tuples::null_type, no_action> na
(nt);
        return na;
}

} // namespace boost
} // namespace spirit

namespace
{

struct append_tuple_to_container_impl
{
    template <typename Container, typename String>
    struct result
    {
        typedef void type;
    };

    template <typename Container, typename String>
    void operator()(Container& c, String const & s) const
    {
                typedef typename Container::value_type tuple_t;
                
                tuple_t t;

                std::istringstream ss(s);

                ss >> boost::tuples::set_open('(')
>> boost::tuples::set_close(')')
>> boost::tuples::set_delimiter(',')
>> t;
                        
                c.push_back(t);
        }
};

phoenix::function<append_tuple_to_container_impl> const
append_tuple_to_container = append_tuple_to_container_impl();

struct insert_as_tuple_impl
{
        template <typename Container,
                          typename T0, typename T1, typename T2, typename T3,
typename T4,
                          typename T5, typename T6, typename T7, typename T8,
typename T9>
        struct result
        {
        typedef void type;
    };

        template <typename Container,
                          typename T0, typename T1, typename T2, typename T3,
typename T4,
                          typename T5, typename T6, typename T7, typename T8,
typename T9>
    void operator()(Container & c,
                                        T0 const & t0,
                                        T1 const & t1,
                                        T2 const & t2,
                                        T3 const & t3,
                                        T4 const & t4,
                                        T5 const & t5,
                                        T6 const & t6,
                                        T7 const & t7,
                                        T8 const & t8,
                                        T9 const & t9)
    {
                c.push_back(boost::make_tuple(t0, t1, t2, t3, t4, t5, t6, t7,
t8, t9));
        }
};

phoenix::function<insert_as_tuple_impl> const insert_as_tuple =
insert_as_tuple_impl();

template <
        typename T0 = boost::tuples::null_type,
        typename T1 = boost::tuples::null_type,
        typename T2 = boost::tuples::null_type,
        typename T3 = boost::tuples::null_type,
        typename T4 = boost::tuples::null_type,
        typename T5 = boost::tuples::null_type,
        typename T6 = boost::tuples::null_type,
        typename T7 = boost::tuples::null_type,
        typename T8 = boost::tuples::null_type,
        typename T9 = boost::tuples::null_type>
struct string_to_tuple
{
        ////////////////////////////////////////////////////////////////////////
////
        // type to boost::spirit parser mapping

        template <typename T, int Dummy = 0> struct parser;

        template <int Dummy> struct parser<boost::tuples::null_type, Dummy>
        {
                static inline boost::spirit::epsilon_parser p()
                {
                        boost::spirit::epsilon_parser result;
                        return result;
                };

                static inline boost::spirit::epsilon_parser comma()
                {
                        boost::spirit::epsilon_parser result;
                        return result;
                }
        };
        
#define PARSER_TRAITS(TYPE, PARSER_T) \
        template <int Dummy> struct parser<TYPE, Dummy> \
        {
                                         \
                static inline
                         \
            PARSER_T p()
                         \
            {
                                 \
                    PARSER_T result;
                 \
                    return result;
                 \
            }
                                 \
                                                                                
                                         \
                static inline
                         \
            boost::spirit::strlit<char const *> comma() \
                {
                                         \
                        boost::spirit::strlit<char const *> str_p(","); \
                        return str_p; \
                } \
        }

        PARSER_TRAITS(int, boost::spirit::int_parser<int>);
        PARSER_TRAITS(unsigned int, boost::spirit::uint_parser<unsigned>);

        typedef boost::spirit::real_parser
        <double, boost::spirit::ureal_parser_policies<double> > real_parser_t;

        PARSER_TRAITS(float, real_parser_t);
        PARSER_TRAITS(double, real_parser_t);

        template <int Dummy> struct parser<std::string, Dummy>
        {
                typedef boost::spirit::contiguous
                <boost::spirit::confix_parser
                 <boost::spirit::strlit<const char*>,
                  boost::spirit::kleene_star
                  <boost::spirit::anychar_parser>,
                  boost::spirit::strlit<const char*>,
                  boost::spirit::unary_parser_category,
                  boost::spirit::non_nested,
                  boost::spirit::non_lexeme> > parser_t;

                                                                                
                 
                static inline
                         
            parser_t p()
                         
            {
                                 
                        using namespace boost::spirit;
                        using namespace phoenix;
                        
                        parser_t result = lexeme_d[confix_p("\"" ,
(*anychar_p) , "\"")];
                        return result;
            }
                                 
                                                                                
                                         
                static inline
                         
            boost::spirit::strlit<char const *> comma()
                {
                                         
                        boost::spirit::strlit<char const *> str_p(",");
                        return str_p;
                }
        };

        // PARSER_TRAITS(std::string, quoted_string_grammar);
        
        ////////////////////////////////////////////////////////////////////////
////
        // typedefs and integral constants

        typedef typename
        boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> tuple_t;

        BOOST_STATIC_CONSTANT(int,
                                                  tuple_len =
boost::tuples::length<tuple_t>::value);

        ////////////////////////////////////////////////////////////////////////
////
        //

        static inline
        std::list<tuple_t>
        apply(std::string const & s)
        {

                using namespace boost::spirit;
                using namespace phoenix;
                
                std::list<tuple_t> result;

                T0 t0; T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8;
T9 t9;

                typedef rule<phrase_scanner_t> rule_t;

                rule_t rule_tuple_rep =
                        (str_p("(")
>> parser<T0>::p()[assign_a(t0)]
>> parser<T1>::comma()
>> parser<T1>::p()[assign_a(t1)]
>> parser<T2>::comma()
>> parser<T2>::p()[assign_a(t2)]
>> parser<T3>::comma()
>> parser<T3>::p()[assign_a(t3)]
>> parser<T4>::comma()
>> parser<T4>::p()[assign_a(t4)]
>> parser<T5>::comma()
>> parser<T5>::p()[assign_a(t5)]
>> parser<T6>::comma()
>> parser<T6>::p()[assign_a(t6)]
>> parser<T7>::comma()
>> parser<T7>::p()[assign_a(t7)]
>> parser<T8>::comma()
>> parser<T8>::p()[assign_a(t8)]
>> parser<T9>::comma()
>> parser<T9>::p()[assign_a(t9)]
>> ")")[insert_as_tuple(var(result),
                                                                         var
(t0), var(t1), var(t2),
                                                                         var
(t3), var(t4), var(t5),
                                                                         var
(t6), var(t7), var(t8),
                                                                         var
(t9))]
                        ;
                
                rule_t rule_tuple_list =
                        *(rule_tuple_rep)
>> end_p // for trailing whitespace
                        ;

                BOOST_SPIRIT_DEBUG_RULE(rule_tuple_rep);
                BOOST_SPIRIT_DEBUG_RULE(rule_tuple_list);

                parse_info<> info;

                try
                {
                        info = parse(s.c_str(), rule_tuple_list, space_p);
                }
                catch (std::exception const & e)
                {
                        std::cerr << e.what() << std::endl;
                }
                
                ENFORCE(info.full)
                        ("Failed to generate a list of tuples from ")
                        ("string representation\n'")
                        (s)("'\n");
                
                return result;
        }
};

} // namespace

#endif // BOOSTTUPLESFROMSTRING_H


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net