Boost logo

Boost :

Subject: Re: [boost] [convert] Now with Boost.Parameter interface.
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2009-07-06 18:16:29


> I've incorporated, uploaded to the Vault and started playing with the
> Boost.Parameter-based interface that Andrey Semashev was insisting from
> the set-go. And it is definitely growing on me and I like
>
> int i = convert<int>::from(str, 0)(locale_ = new_locale)(throw_
> =
> true);
>
> instead of the original
>
> int i = convert<int>::from(str, 0) >> new_locale >> dothrow;
>
> I think people generally did not like locales and dothrow behaving like
> manipulators.

Sorry if I'm late here. Either of both ways just feels wrong as not all of
the manipulators/parameters are of general use. The radix_ parameter
described elsewhere is a good example for a parameter applicable to string
<--> integer conversion only. It is highly confusing not to get a compile
time error while specifying a wrong parameter (a parameter not being
applicable for the type to convert to/from).

For instance, what is supposed to happen if I do:

    convert<double>::from(str, radix_ = 16)

?

The current approach in my view mixes things not belonging together. A
conversion library needs to keep apart data and formatting information. This
is not done here. Formatting and data type are spread over the whole
expression, making it very difficult to get things right.

I believe this is a strength of Spirit's approach, where data and formatting
are clearly separated. Applying a similar approach to convert would result
in:

    double d = convert::from(str, double_);
and
    std::string s = convert::to(d, double_);

where double_ is an example for a placeholder allowing to specify arbitrary
formats (remember, Spirit allows to build more complex formats/grammars out
of simpler ones, while providing all necessary primitive type conversions).
For instance, applying a different locale to this results in:

real_spec<double> locale_double(new_locale);

    double d = convert::from(str, locale_double);
and
    std::string s = convert::to(d, locale_double);

where real_spec (choose a different name, if you like) creates a new
placeholder encapsulating all formatting information needed to do the
conversion.

This has the additional advantage of providing a nicely extensible
framework. Any non-foreseeable formatting requirements are easily
customizable.

OTOH, general parameters applying directly to the conversion process (such
as throwing behavior or default values) are fine to be passed as additional
arguments. But care must be taken not to intermix this with formatting
related parameters (and yes, believe me or not, locales _are_ formatting
related). So I think the following would be ok:

    double d = convert::from(str, double_, default_ = 0.0);
and
    std::string s = convert::to(d, double_, throw_ = true);

BTW: this interface above is easily implementable on top of Spirit. It's
just a thin wrapper around existing functionality. And I already expressed
my opinion that any high level conversion library should be built on top of
Spirit - a proven, fast, reliable, versatile, and mature parser and
generator framework. Anything else leads to code duplication,
inconsistencies, implementation flaws, you name it. Converting a string of
digits into an integer might seem to be an easy task. But it's not. It's
tricky, error prone, and difficult to get correct _and_ fast at the same
time.

But all that is certainly purely IMHO.
Regards Hartmut


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