Boost logo

Boost :

Subject: Re: [boost] Review Request: Introduction of boost::string namespace and string-conversion functions
From: Vladimir.Batov_at_[hidden]
Date: 2009-02-12 16:15:09


Thank you all who replied so far. It is very much and truly appreciated.
Tally for far

1. The idea in principle seems to be largely accepted.

Phil Endecott raised a concern if the effort was not a wheel-reinvention
due to string/number conversions in N2408. I feel N2408 does not have as
broad scope and has serious limitations (no user-type conversions, no
handling of any container<char>, etc.)

2. The name of the namespace.

People largely seem content with "boost::string".

Andrey Semashev expressed a concern that the name was too generic and
could clash with std::string (using namespace boost; using namespace std).
A fair point. However, I do not feel it is a boost::string "problem" per
se but rather the "problem" with using-directives (or rather
mis-using-directives). Using-directives beat the whole purpose on a
namespace and best avoided (see Stroustrup 8.2.3). From my actual
experience it was not an issue. Long time ago I've introduced aux::string
in two sizeable projects and honestly did not have one single complain
about name clashing.

Bo Persson also expressed a concern siting it'll make it "very hard to
propose the utilities for inclusion in a future language standard". May
be. May be not. When things of that magnitude happen (which seem quite
remote at present) components get moved from a namespace to a namespace
(several times) anyway. Like some stuff from the "boost" namespace moving
to the "tr1" namespace just ultimately to be moved to the "std" namespace.

Therefore, unless something major comes up later we are settling on
"boost::string".

3. Naming of the conversion functions.

The "to/from/is" set seems to sit well with the majority of people.

The to_string/from_string was floated around as alternatives. I feel that
the "_string" extension indeed serves a mildly useful purpose when the
"string" namespace is obfuscated. Like

        namespace boost::string obfuscated;

        string str = obfuscated::from(i); // What the...?
        string str = obfuscated::to_string(i); // Somewhat better but
still...

When used sensibly

        string str = boost::string::from(i);
or
        namespace boost::string str;
        string str = str::from(i);

the intention seems clear and the following feels like a tautology:

        string str = boost::string::to_string(i);

Robert Stewart mentioned that "is" is a poor name choice. It doesn't
imply "can convert to" and can be expensive to execute. Fair enough. I'll
keep the name around as a placeholder for a rainy day. We might not need
it at all if we agree on something along the following lines:

        // No throw, return default on failure, dunno if failed.
        int i = boost::string::to<int>(str, default_value);

        // No throw, return default on failure, can check if failed.
        boost::string::value i = boost::string::to<int>(str,
default_value);
        if (i.good()) successfully converted

4. String-To-Something Conversion Interface.

Considerable number of people were not exactly happy with my off the cuff

        int i = boost::string::to<int>(str)(default_value);

Well, I do not like it either... I just like saying/suggesting things that
I regret later. :-) I probably got carried away by the
functional-chain-ability concept.

The main reason (for me) it is not good is that it imposes the
default-constructibility requirement. I think people on the original
lexical_cast-realted thread were pretty content with

        int i = boost::string::to<int>(str, -1);

syntax. If so, then we won't need

        int i = to(str).or_default(-1)
        int i = to(str, default_ = -1)

Can we agree on the following interface:

        template<class T, class String>
        boost::string::value<T>
        boost::string::to(String const&, T const& =T()) throw();

The usage is

        // Does not throw, returns -1 on failure. Don't care if failed
        int i1 = boost::string::to<int>(str, -1);
        // Does not throw, returns -1 on failure. Care if failed
        boost::value<int> i2 = boost::string::to<int>(str, -1);
        if (i2.good()) successful conversion6.

5. Formatting with manipulators.

I've implemented a prototype and it works just fine.

        string str = "0xFF";
        int i1 = boost::string::to<int>(str, -1) >> std::hex; // returns
255
        int i2 = boost::string::to<int>(str, -1)(std::hex); // Same as
above

For the time being I keep both interfaces (via () and >>).

6. Something-To-String Conversion Interface.

That did not seem to generate much heat at all. I'll summarize to make
sure we see it the same way:

        template<class T>
        boost::string::value<std::string>
        boost::string::from(T const&) throw();

Does not throw. No default value (do we need one?). Returns string() of
failure. Usage:

        std::string s1 = boost::string::from(-1); // 'int' type deduced
        std::string s2 = boost::string::from<double>(-1); // 'double' type
forced
        std::string s3 = boost::string::from(15) >> std::hex; // returns
"0xF"
        if (s1.empty()) conversion failed
        boost::string::value<std::string> s4 = boost::string::from(-1);
        if (s4.good()) conversion succeeded

7. Check-Convertibility Interface.

If we agree on the behavior above (using boost::string::value), then the
separate boost::string::is does not seem needed.

8. Throw/No-Throw Behavior.

You might have noticed that the interface above *never* throws anything on
failure. I would like to highlight the fact (as it's different from
lexical_cast behavior) and make sure people are happy with it. Those who
need an exception thrown could do

        boost::value<int> i2 = boost::string::to<int>(str, -1);
        if (!i2.good()) throw something youself;

Is it satisfactory?

9. Requested features.

a) Handling any container<char> (Phil Endecott). I implemented a rough cut
using boost::range and it handles std::(w)string, char/wchar_t const* with
ease. To handle any container we might look into extending the interface
with something like

        template<class T, class Range>
        boost::string::value<T>
        boost::string::to(Range const&, T const& =T()) throw();

I have not looked into it throughly yet though.

b) Integration with Spirit (Hartmut Kaiser). My focus is currently on the
interface. Then, we can look at Spirit+boost-string behind it as a
separate issue as it requires Joel (and other Spirit developers) involved.

c) locale. I have not looked into it at all and I am not sure I am
well-qualified. OTOH I hope it'll fit into the proposed interface as

        string s3 = boost::string::from(15) >> std::hex >>
locale-related-functionality;
or
        string s3 =
boost::string::from(15)(std::hex)(locale-related-functionality);

If so, then we can return to the issue when we get all the above taken
care of.

Thanks,
Vladimir.


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