Boost logo

Boost Users :

From: Terje Slettebų (tslettebo_at_[hidden])
Date: 2005-01-29 21:54:29


>From: "Yuval Ronen" <ronen_yuval_at_[hidden]>

> Terje Slettebų wrote:
>
> > I've brought this thread to Kevlin Henney's attention, as I've tended to
> > take care of lexical_cast related questions on the list (including
> > forwarding things needing his consideration, such as any changes to
> > lexical_cast, to him). I'm replying here to let you know that your
report is
> > being taken care of.
>
> Many, many thanks!

Thanks, yourself. :) Feedback is always welcome (regardless who's library it
is); it's an opportunity to improve it.

> >>1. lexical_cast(Source arg) takes the source argument by value. Why not
> >>by const& ? Calling lexical_cast(some_basic_string) now makes a copy of
> >>the source argument for no reason.
> >
> > I heard from Kevlin that the reason was that there originally were some
> > issues with binding to string literals. Changing it to use const
reference
> > in my local copy still gives a lot of error messages, having to do with
> > std::numeric_limits being used in the implementation. If we find a way
to
> > fix this (yet letting it still work on compilers with no class template
> > partial specialisation, like MSVC 6), without breaking existing
programs,
> > then apparently, this change should be ok. If anyone makes a patch for
this,
> > it would be welcome.
>
> Hmmm, interesting. I'll give it a look. Maybe I'll be lucky enough to
> think of something...

I've been looking at this, as well, and after trying one approach (doing a
compile-time switch to select between the ordinary, and a "dummy"
std::numeric_limits (if the source type is an array)), I bumped into another
problem: the specialisations for wchar_t, which assumes "const wchar_t *",
not "const wchar_t[...]". This might again be fixed, using partial
specialisation, to work with array, but another approach could be to "go
back to square one" and do the array-to-pointer decay "manually":

    template<typename Target, typename Source>
    Target lexical_cast(const Source &arg)
    {
        // Array-to-pointer decay

        typedef typename mpl::if_<
          is_array<Source>,
          add_pointer<add_const<remove_bounds<Source>::type>::type>::type,
          Source
>::type NewSource;

        detail::lexical_stream<Target, NewSource> interpreter;
        Target result;

        if(!(interpreter << arg && interpreter >> result))
            throw_exception(bad_lexical_cast(typeid(NewSource),
typeid(Target)));
        return result;
    }

This passes all tests on Intel C++ 7.1, MSVC 7.1 and g++ 3.2. I've sent it
as a suggestion to Kevlin, as well, I think he's pretty busy with other
things. Anyone having a better suggestion than the above is of course
welcome to contribute it. One thing about the above change is that it
requires a few more includes, but this is really the simplest way I found to
be able to use pass by const reference for lexical_cast.

The additional includes are:

#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/remove_bounds.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/mpl/if.hpp>

Regards,

Terje


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net