Boost logo

Boost :

Subject: Re: [boost] boost::string namespace and string-conversion functions
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2009-02-14 11:38:18


> > Boost already has a library for that problem:
> > Spirit. With Spirit2, in fact, my understanding is that it has a
> > consistent way to both directions as well. (Arguably serialization
> > does as well, but there any parsing is an implementation detail.)
>
> I am glad you brought it up. Something along these lines was nagging me
> as I
> was using boost::serialization for ultimately conversion to/from XML
> (i.e.
> string) and Hartmut mentioned Spirit capable of doing conversions. So,
> I was
> wondering if that my noise about conversion was not mis-guided. I
> played
> with Spirit (the parser part) only a little bit. I only managed to
> write a
> half-a-page parsing grammar just to happily replace it with a two-liner
> regular expression. Never looked back.
>
> Could you show how to convert int-to-string-to-int with Spirit? Can we
> apply
> hex/scientific/etc. formatting? Does it deal with user types (as
> lexical_cast does)?

    namespace qi = boost::spirit::qi;
    namespace karma = boost::spirit::karma;

    int i = 0;
    if (qi::parse("1", int_, i))
        karma::generate(outiter, int_, i);

where outiter is some output iterator. 'int_' is only one of the available
primitives, there are more: uint, long_, ulong, double_, float_, you get the
picture. Full customization for special formats is provided, just write your
own policies. Example:

    template <typename T>
    struct scientific_policy
      : karma::real_generator_policies<T>
    {
        // we want the numbers always to be in scientific format
        typedef karma::real_generator_policies<T> base_type;
        static int floatfield(T) { return base_type::scientific; }
    };

    typedef karma::real_spec<double, scientific_policy<double> >
        science_type;

    double d = 1.2345;
    karma::generate(outiter, science_type(), d);

which will generate: "1.234e00" (the default number of fractional digits is
3, but this can be changed easily as well).

etc.

the parse/generate functions are just one possible interface, another is to
use iostream base manipulators:

    int i = 0;
    std::ci >> qi::match(int_, i);
    std::cout << karma::format(int_, i) << std::endl;

HTH
Regards Hartmut


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk