Boost logo

Boost :

From: Alberto Barbati (abarbati_at_[hidden])
Date: 2002-08-21 17:23:55


Hi All,

a discussion on an STLport forum triggered a little discussion on
lexical_cast. I believe that current implementation has a couple of flaws:

1) it requires that both the Target and Source type have a operator>> and
operator<<, respectively. There are situation in which it is desirable not
to define those operators (for example, SGI rope does not have the
operator>>). It's true that you can always provide something that you don't
have...

2) sometimes, operator<< or operator>> may perform a task different than the
one suitable by lexical_cast. For example, suppose you have class vector3d
whose operator<< produce output in the format "(x, y, z)" (notice the two
spaces!). It's reasonable (at least, it's reasonable to me) that the
expression

boost::lexical_cast<std::string>(vector3d(0, 0, 0));

should return the string "(0, 0, 0)", however an exception will be thrown
because operator<<(istream&, string&) stops at the first space.

Notice that in both cases, the "problematic" type is the Target. In fact you
could solve the problem via overload if it was the Source type, but you
can't overload according to the return type. In order to solve both issues
and also gain a bit or flexibility the simplest solution would to use two
helper functions, like this:

template<typename Source>
inline bool lexical_cast_inserter(std::ostream& interpreter, const Source&
s)
{
        return (interpreter << s).good();
}

template<typename Target>
inline bool lexical_cast_extractor(std::stringstream& interpreter, Target&
t)
{
        return (interpreter >> t).good() && (interpreter >> std::ws).eof();
}

Target operator()(Source arg) const
{
    std::stringstream interpreter;

    Target result;
    if(!lexical_cast_inserter(interpreter, s) ||
!lexical_cast_extractor(interpreter, result))
        throw bad_lexical_cast();
    return result;
}

The reason why the first argument in lexical_cast_extractor is
std::stringstream and not std::istream is just to allow possible
optimizations (see below). Then we could write (or let the user write)
specializations for string and rope like this:

template<>
inline bool lexical_cast_extractor(std::stringstream& interpreter,
std::string& t)
{
        t = interpreter.str();
        return true;
}

template<>
inline bool lexical_cast_extractor(std::stringstream& interpreter,
std::crope& t)
{
        t = interpreter.str().c_str();
        return true;
}

Does this make sense to anyone?

Alberto Barbati


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