Boost logo

Boost :

From: Craig Henderson (cdm.henderson_at_[hidden])
Date: 2002-07-22 15:44:45


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)
    {
    # ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
        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. 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?

template<typename Target, typename Source, typename E>
inline Target lexical_cast_interpreter(Source arg)
{
    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)
{
# ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
    typedef std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# else
    typedef std::basic_stringstream<char> interpreter;
# endif
    return lexical_cast_interpreter<Target, Source, interpreter>(arg);
}

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);

Could this amendment be made to the boost header to extend support to
multi-byte characters?

-- Craig


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