Opened 10 years ago

Last modified 9 years ago

#7929 new Bugs

boost::lexical_cast< std::string, std::wstring > gives a compiler error.

Reported by: nate@… Owned by: Vladimir Prus
Milestone: To Be Determined Component: program_options
Version: Boost 1.52.0 Severity: Problem
Keywords: Cc: antoshkka@…

Description

This causes a problem with boost::program_options::typed_value< std::wstring, wchar_t >::default_value( const std::wstring& v ) which attempts to use lexical_cast to convert v into a std::string. Using lexical_cast to convert a wide string to a normal one may be debatable, but program_options should not give a compiler error on a valid use case such as the one shown below. Luckily you can work around this by providing an explicit std::string version or not using the default_value method at all.

lexical_cast error

#include <boost/lexical_cast.hpp>
#include <string>

int main( int argc, wchar_t* argv[] ){
    std::wstring wstr = L"some string";
    std::string str = boost::lexical_cast< std::string >( wstr );

    return 0;
}

program_options error

#include <boost/program_options.hpp>
#include <string>

int main( int argc, wchar_t* argv[] ){
    namespace po = boost::program_options;
    po::options_description opts( "Some opts" );

    std::wstring str = L"";
    opts.add_options()
        (
            "o",
            po::wvalue< std::wstring >( &str )
                ->default_value( L"default value" ), // This line causes error.
            "an option"
        );

    return 0;
}

Change History (4)

comment:1 by Antony Polukhin, 10 years ago

Cc: antoshkka@… added
Component: lexical_castprogram_options
Owner: changed from Antony Polukhin to Vladimir Prus

I'm afraid that this is not a bug of lexical_cast. Lexical_cast shall work like a std::stringstream/std::wstringstream, so the first example is equal to the following:

#include <sstream>

int main() {
    std::wstringstream wss(L"some string");
    std::string str;
    wss >> str;  // Compilation error

    return 0;
}

And this code must not compile (if I'm wrong and my current compiler fail to compile a correct code - please tell me about it).

So, this looks more like a program_options bug.

comment:2 by nate@…, 10 years ago

I'm not sure I agree that lexical_cast is just supposed to be a wrapper around std::stringstream when its own documentation states:

The lexical_cast function template offers a convenient and consistent form for supporting common conversions to and from arbitrary types when they are represented as text.

That, to me, sounds like it should work for converting std::wstring to std::string. It is an common conversion dealing with arbitrary types and text.

comment:3 by Antony Polukhin, 10 years ago

To be honest, I also miss that functionality sometimes.

But before implementing it, I need to

  • fix existing issues with std::locale on some compilers
  • determinate a portable and reliable way to do narrowing of characters (it looks almost impossible to me)

So this won't be fixed in nearest future. And I'm afraid that Boost.Locale shall be used in such cases...

comment:4 by nate@…, 9 years ago

Perhaps one can look to the standard library for inspiration? In the locale header there is the std::codecvt class which can be used with std::wstring_convert to perform convertions from one encoding to another.

Below is an example using the C++11 class std::codecvt_utf8_utf16 to convert a UTF-16 std::wstring to a UTF-8 encoded std::string. I am using this in my application to great success so far.

    std::wstring wideString;
    std::wstring_convert<
        std::codecvt_utf8_utf16< std::wstring::value_type >,
        std::wstring::value_type
    > utf16conv;
    std::string narrowString = utf16conv.to_bytes( wideString );

I hope this helps to show a potential way to narrow characters.

Note: See TracTickets for help on using tickets.