Boost logo

Boost :

Subject: Re: [boost] [review] string convert
From: Vladimir Batov (vbatov_at_[hidden])
Date: 2011-05-09 20:23:58


> Stewart, Robert <Robert.Stewart <at> sig.com> writes:
>
>> T convert::to<T>(S, boost::parameter-list);
>
> Vicente has been discussing the issue of stream-based conversions WRT
> manipulators. In
> lexical_cast-style conversions, there's an insertion followed by an
> extraction. Are manipulators
> needed for both directions? If so, the interface must allow for them using,
> say, "in" and "out" keywords instead of "format_."

There has been no need for that. The original 'convert' was applying
manipulators in both directions. The in/out direction is defined by the
string-to-type or type-to-string specialization.

> to<T>() seems a very nice name for stream-based conversions. It can be
> qualified by the namespace name,

The original 'convert' was a struct working as a namespace, i.e. one had to say
convert::to/from.

> convert::to<T>(), or not and it is still readable. That function can, one
> way or another, provide support
> for manipulators while convert_cast<T>() can skip them. That means that
> to<T>() can be used for
> stream-based conversions and convert_cast<T>() for non-stream-based
> conversions. Whether the
> latter must provide any l10n support is for others to determine as I simply
> don't know enough to say.

I am not sure why that distinction has to be made. Now that converters are gone
and all parameters are provided in one call, the implementer knows what
conversion is needed. That is, if there are no 'format_' parameters specified,
then, say, spirit-based quick conversion is applied. As soon as I see 'format_',
then I fall back to stream-based. So, all we seem to need is convert::to.

>> Then we specialize it for convert::result type so that
>>
>> convert::result<T> convert::to<result<T>>(S, boost::parameter-
>> list);
>
> That strikes me as a very nice compromise.

Glad to hear that.

>> // The predictable. Throws on failure
>> int i = convert::to<int>("FF", (format_ = std::hex))
>
> Good for stream-based formatting.
>
> convert_cast<int>("FF") would be the non-streams-based equivalent.

As I said, I'd expect the following to be the non-streams-based equivalent:

int i = convert::to<int>("FF")

>> // The predictable. Returns fallback on failure
>> int i = convert::to<int>("FF", (fallback_ = 255, locale_= ...,
>> format_ = std::hex, throw_ = true))
>
> Good for stream-based formatting. I presume you meant "throw_ = false."

Indeed, I meant *no* 'throw_' parameter (which is "throw_ = false.").

> I think nothrow (or similar) is
> better than "throw_ = false," however.
>
> try_converting_to<int>("FF", 255) would be the non-streams-based equivalent.

Again, I'd like to re-iterate (as I think it's quite important) that the choice
of the best available converter is done internally based on supplied parameters.
Therefore, no need to stream- and non-stream-based variants.

> ...
>> // The 'try' version
>> int v = 255;
>> bool success = convert::try_to<int>("FF", v, (locale_= ...,
>> format_ = std::hex))
>
> I don't like that name. "to<int>" says the right thing. "try_to<int>"
> doesn't. It makes me think "int" is a
> verb, as in "try to jump."

I am not a fan either (with modifiable ref-passing). In my world it does not
exist. So, I'll stand aside while others discuss this func/name.

> This leaves the fate of the converter function objects unclear. That
> functionality seems too useful to
> drop.

I am not sure converters are needed as we can feed convert::to() to algorithms
with 'bind' or 'lambda' .

> To summarize, here's the complete API as I see it now:
>
> 1. convert::default_value<T> customization point
> * Default value, if needed, when not otherwise supplied

I expressed my opposition to default_value. It was not needed for the original
'convert', i.e. we can get away without it. Asking the user to supply this
arbitrary functionality is bothersome and will be mis-used/abused.

> 2. convert::converter<T,S> customization point
> * Non-stream-based main logic
> * Functor interface

I am not sure converters are needed as we can feed convert::to() to algorithms
with 'bind' or 'lambda' .

> 3. T convert::convert_cast<T,S>(S)
> * Throws on failure unless T is convert::result<T'>
> * Uses convert::converter<T,S> to do conversion

T convert::to<T>(s) seems to work as well. Less API to remember.

> 4. T convert::convert_cast<T,S>(S, T _fallback)
> * Returns _fallback on failure unless T is convert::result<T'>
> * Uses convert::converter<T,S> to do conversion

T convert::to<T>(s, (fallback_ = ...)) seems to work as well. Less API to
remember.

> 5. bool convert::try_converting_to<T,S>(S, T & _value)
> * Returns false and leaves _value unchanged on failure
> * Uses convert::converter<T,S> to do conversion

If people want it. I'll be using

convert::result<T> convert::to<convert::result<T>>(s) instead. Less API to
remember.

> 6. convert::stream_converter<T,S> customization point
> * Stream-based main logic
> * Functor interface
> * Supports manipulators

I am not sure converters are needed as we can feed convert::to() to algorithms
with 'bind' or 'lambda' .

> 7. T convert::as<T,S>(S, options)
> * Throws on failure
> * Uses convert::stream_converter<T,S> to do conversion
>
> 8. T convert::as<T,S>(S, T _fallback, options)
> * Returns _fallback on failure
> * Uses convert::stream_converter<T,S> to do conversion

The fallback could be provided again via boost::parameter-list as

T convert::to<T>(s, (fallback_ = ...)) seems to work as well. Less API to
remember. (I user convert::to instead of convert::as. Not sure if convert::as
was intentional or accidental).

> 9. bool convert::try_as<T,S>(S, T & _value, options)
> * Returns false and leaves _value unchanged on failure
> * Uses convert::stream_converter<T,S> to do conversion

That's a lot. I'd seem to manage with just convert::to. :-) ... even though it
did not make it onto the list.

> If that's a decent API, and since it represents the combination of the
> functionality in both Vicente's and
> your library, perhaps the two of you could collaborate on it and produce a
> new Boost.Convert proposal.
> (I'd prefer Boost.Convert to Boost.Conversion because the namespace name is
> shorter and more useful
> when reading names like "convert::as.")

I do not want to slow Vicente down and I am happy for Vicente to steam ahead if
he feels like it... if he is willing to cover use-cases described in the
original 'convert' proposal. Although so far I did not get that impression that
Vicente was covering the original 'convert' cases. If that's changed and I
missed it, great.

V.


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