Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost program arguments can parse a wstring, but forces it into a string?

Tags:

c++

boost

I am parsing command line arguments with wide strings using boost::program_options. I have the following code:

namespace po = boost::program_options;
po::options_description desc("Allowed options");
desc.add_options()
    ("silent", po::value<std::wstring>()->default_value(L"yes"), "Select the verbosity")

po::variables_map vm;
po::wcommand_line_parser parser(args);
po::wparsed_options parsedOptions = parser.options(desc).style(1).run();
po::store(parsedOptions, vm);
po::notify(vm);

But i get the error:

Error C2678 binary '>>': no operator found which takes a left-hand operand of type 'std::basic_istream>' (or there is no acceptable conversion)

From the add_options functional line. I understand that operator>> and operator<< don't work with wstrings. But boost specifically supplies the wcommand_line_parser (note the w) for wide string command line argument parsing. But it doesn't look like there is a way to actually retrieve that argument result as a wide string.

Is there a work around for this or am I doing something incorrectly?


Note: The code can be compiled with this change:

desc.add_options()
("silent", po::value<std::string>()->default_value("yes"), "Select the verbosity")

But then you will lose unicode information from the string. Not sure exactly what the result will be from this conversion, or how it is done.

like image 205
Fantastic Mr Fox Avatar asked Oct 23 '25 22:10

Fantastic Mr Fox


1 Answers

You need two things:

  • use wvalue
  • supply the narrow-char text representation of the default value for use in the usage description text.

    Note that you quoted the error from the add_options line. The problem is adding the option description, not parsing it.

    The reason is that option descriptions are char-based always (you knew this because the description and option names are narrow too). When getting the textual representation of the default value, Boost PO tries to use the ostream operator¹ and that doesn't work for your wchar_t const* or std::wstring value.

    The same happens with non-streamable custom option types, so you can pass the textual representation manually (e.g. default_value(std::vector<int>{1,2,3}, "1-3") for some multi-valued option that parses ranges).

DEMO

You get:

See it Live On Coliru

#include <boost/program_options.hpp>

namespace po = boost::program_options;

int main() {
    po::options_description desc("Allowed options");
    desc.add_options()
        ("silent", po::wvalue<std::wstring>()->default_value(L"yes", "yes"), "Select the verbosity")
        ;

    po::variables_map vm;
    std::vector<std::wstring> args { L"--silent=no" };
    po::wcommand_line_parser parser(args);
    po::wparsed_options parsedOptions = parser.options(desc).style(po::command_line_style::default_style).run();
    po::store(parsedOptions, vm);
    po::notify(vm);
}

NOTE

In this particular example you might want po::bool_switch() instead of po::xvalue()


¹ (eventually, via Boost Lexical Cast)

like image 123
sehe Avatar answered Oct 25 '25 13:10

sehe