Boost logo

Boost :

From: Gennaro Prota (gennaro_prota_at_[hidden])
Date: 2002-07-23 12:14:47

On Mon, 22 Jul 2002 21:44:45 +0100, "Craig Henderson"
<cdm.henderson_at_[hidden]> wrote:

>The lexical_cast<>() function does not respect character traits. I work on a
>Win32 platform with MSVC which supports char and wchar_t for 8-bit and
>16-bit character representation, respectively. lexical_cast<>() uses a
>std::stringstream which is a synonym for template class basic_stringstream,
>specialized for elements of type char.
>Unfortunately, adding a third (default) template parameter to define the
>character type, thus
> template<typename Target, typename Source, typename E=char>
> Target lexical_cast(Source arg)
> {
> std::strstream interpreter; // for out-of-the-box g++ 2.95.2
> # else
> std::basic_stringstream<E> interpreter;
> # endif
> }
>fails to compile with on both MSVC and g++ 2.95.3-5 on Cygwin as the
>templates cannot be deduced.

Specifying a default template argument for a function template is
currently prohibited by the standard, but it's likely that this
limitation will be removed in the future, as asked by B. Stroustrup

It is substantially a residual of the past that remained unnoticed and
that anyone assumed not to exist anymore; in fact paragraph 13.4.1 of
'The C++ programming language' is in direct contradiction with it.

> However, I have managed to solve the problem
>with the introduction of a second template function, as shown below. The
>original function has been renamed lexical_cast_interpreter<>() and has
>three template parameters. The new third parameter defines the interpreter
>type. The new function actually takes the name of the old one, as it is a
>direct replacement. The conditional compilation for g++ is in this function
>and typedefs the interpreter that is passed as a template parameter to the
>replacement function - a kind of round-about default parameter. Note that
>gcc allowed the function to be overloaded with three template parameters,
>however, MSVC complains about a 'mismatch in formal parameter list', and
>hence the different names. I don't really like 'lexical_cast_interpreter',
>does anyone have any better name suggestions?

Well, a possible but ugly workaround is:

// ---- untested code ----

template<typename Target, typename Source, typename E>
inline Target lexical_cast(Source arg, E& interpreter)
    //E interpreter;
    Target result;

    if(!(interpreter << arg) || !(interpreter >> result) ||
       !(interpreter >> std::ws).eof())
        throw bad_lexical_cast();

    return result;

template<typename Target, typename Source>
inline Target lexical_cast(Source arg)
  typedef std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# else
    typedef std::basic_stringstream<char> interpreter;
# endif

    interpreter in;
    return lexical_cast<Target, Source>(arg, in);

The main disadvantage is that in the general case you have to pass an
instance of the interpreter type. The main advantage (?) is that you
are not limited to default construct it so, theoretically, you could
pass some sort of "special interpreter". If we don't need the second
option other solutions are possible anyway. We should hear what others
have to say about that.

> [original code snipped...]
>Now I can use this to create a wide-character string
> std::basic_string<wchar_t> str = lexical_cast_interpreter<
>std::basic_string<wchar_t>, int, std::basic_stringstream<wchar_t> >(123);

With the code above it becomes:

std::basic_stringstream<wchar_t> use_this;

std::basic_string<wchar_t> str =
     lexical_cast< std::basic_string<wchar_t> >(123, use_this);


Boost list run by bdawes at, gregod at, cpdaniel at, john at