Boost logo

Boost :

From: Jonathan Wakely (cow_at_[hidden])
Date: 2004-07-16 10:04:41


On Fri, Jul 16, 2004 at 03:06:20PM +0200, Michiel Salters wrote:

> > -----Original Message-----
> > From: boost-bounces_at_[hidden]
> > [mailto:boost-bounces_at_[hidden]]On Behalf Of Jason
> > Sent: vrijdag 16 juli 2004 11:03
> > To: boost_at_[hidden]
> > Subject: [boost] lexical_cast reviewed
> >
> > SOURCE CODE:
> > #include <sstream>
> > using namespace std;
>
> > class lexical_cast {
> > public:
> > template <typename Source> lexical_cast( const Source & source ) {
> > ss << source;
> > }
> >
> > template <typename Target> operator Target() {
> > Target target;
> > ss >> target;
> > return target;
> > }
> > private:
> > stringstream ss;
> > };
>
> Not really lexical_cast, but useful nevertheless. Perhaps we could call it
> lexical_auto_cast. It could be more efficient to store a string instead, but
>
> I'm not sure.

That would mean the lexical_cast ctor constructs a string member,
constructs a local stringstream, inserts Source into the stream,
assigns to the string, then destroys the local stringstream.
Then when the conversion takes place another local stringstream is
created, copying the contents of the string, then Target extracted,
then the stringstream is destroyed.
In the dtor the string member is destroyed.
This is an extra std::string ctor/dtor and an extra std::stringstream
ctor/dtor over the original, and at least one copy of the string data,
maybe more (depending on how the string is implemented).

As for the original suggestion - I like the fact that lexical_cast<T>()
is consistent with the syntax of const_cast<T>(), static_cast<T> etc.
so I don't think the name should include "cast" unless it matches that
syntax.

There should also be error-checking in the conversion operator, to check
that the stream state is good before (in case insertion failed) and
after extracting. Can't check in ctor since the Target type isn't known
yet. (Obvious I know - just thinking out loud ... )

Also, I think Jason's version would fail in this case, that the original
supports:

    struct A {
      A(const B&);
    };
    struct B {};
    struct C {};
    std::ostream& operator<<(std::ostream&, const C&);
    std::istream& operator>>(std::istream&, const B&);

    A a = boost::lexical_cast<B>( C() ); // OK

    A a = lexical_cast( C() ); // ERROR, no op>> for A

Similarly if B has "B::operator A() const" instead of A having non-explicit
"A::A(const B&)" ctor.

I'm not sure how important this is, since it should be possible to
construct pathological cases that the original version fails with too.

jon

-- 
"It is easier to port a shell than a shell script."
	- Larry Wall

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