$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] Formal Review Request: Boost.Convert
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2009-02-24 13:43:59
Sorry for the late reply, it's been a busy weekend. I'm glad to see that
others answered some of your questions.
Vladimir Batov wrote:
>> You can add new keywords as needed.
>
> Where can I add those "new keywords" to? If it is into convert(), then
> I do not feel it is appropriate as for every user "needed" will be
> different and I cannot see convert() collecting *all* those "needed"
> keywords from every user on the globe.
>
>> The point is that the underlying conversion mechanism can support a
>> subset of these keywords, specific to the conversion domain. This way
>> it will be a non-intrusive extension.
>
> I cannot understand how it can be a "non-intrusive extension" if every
> new keyword needs to be stored/registered *inside* convert<string,
> int>... unless I misunderstand something. With manipulators (however
> clumsy they are) convert<string, int> knows nothing about std::hex.
> Still, when std::hex is plugged in, we get 0xFF. How do you do that with
> "radix_"? The keyword has to be registeded with convert<string, int> and
> then convert<> needs to apply that somehow.
My initial post wasn't specifically about string-related conversions,
however, the main plot is still applicable.
Assume we want to make a numeric conversion, but we also want to detect
truncation and treat it as an error:
int i = 0xFFFFFFFF;
short j = convert< short >(i, throw_on_overflow_ = true);
Now, that kind of conversion could be handled by
Boost.NumericConversion, something like this (pseudocode):
BOOST_PARAMETER_KEYWORD(throw_on_overflow_)
template< typename ToT, typename ArgsT >
ToT convert_impl(ArgsT const& args)
{
bool throw_on_overflow = args[throw_on_overflow_ | false];
return numeric_cast< ToT >(args[source_], throw_on_overflow);
}
You can see that the convert_impl accepts a single arguments pack that
accommodates all named arguments passed to the "convert" function,
including the source value i, which has the implicit name "source_". You
can also see that the "throw_on_overflow_" keyword belongs to the
Boost.NumericConversion library, and Boost.Convert does not need to know
anything about it.
As for the "string<->numeric" conversions, the approach is the same with
one exception: such conversions can be made by Boost.Convert itself.
This means that Boost.Convert may introduce its own keywords to
customize the conversion (such as radix_, bool_alpha_, etc.)
One dark corner that needs to be settled in this scheme is to figure out
how Boost.Convert will decide which convert_impl should be called. This
needs to be thought about, however, I think, using a number of traits on
the source and target types, yielding some tag type to dispatch between
convert_impl functions would suffice.
> Secondly, I do not feel there is much conceptual difference between
>
> convert<string, int>(str, radix_ = 16)
> and
> convert<string, int>(str).radix(16) // 16 passed in differently
> or
> convert<string, int>(str) >> radix(16) // different op>>
> or
> convert<string, int>(str) >> std::hex
>
> The difference is that in #1 convert() has to handle "radix_" itself and
> in #4 convert() knows nothing about std::hex. Am I missing something?
Like I said, using manipulators is sufficient for string-related
conversions, but is pretty meaningless for other types of conversion.
You could implement your own manipulator-like modifiers even for other
conversions, but it would look unnatural and more complex than using
keywords. For example, here's how wstring->string conversion could look
like:
string s = convert< string >(ws) >> replace_non_convertible_with('?');
or:
string s = convert< string >(ws, replace_non_convertible_with_ = '?');
Personally, the latter looks more appealing to me.
> RE: algorithms
>
> I've extended convert to be used with algorithms as
>
> std::vector<string> strings;
> std::vector<int> integers;
> ...
> std::transform(
> strings.begin(),
> strings.end(),
> std::back_inserter(integers),
> convert<string, int>(string(), -1));
>
> No formatting. I feel it is the best I can do (well, so far).
Do you intentionally use the "convert" verb for the functor name?
Traditionally, functors and other classes use nouns in their names, like
"converter".