Boost logo

Boost Users :

Subject: Re: [Boost-users] program_option parsing error
From: Vladimir Prus (vladimir.prus_at_[hidden])
Date: 2015-09-29 15:36:12


On 29-Sep-15 3:00 PM, Marek Skalický wrote:
> Vladimir Prus píše v Čt 24. 09. 2015 v 12:13 +0300:
>> Hi Marek,
>>
>> On 23-Sep-15 4:41 PM, Marek Skalický wrote:
>>> Hello everyone,
>>> I have a question about program_option library.
>>>
>>> If I have argv=["binaryname", "--port", "5"] and port have set
>>> default_value=6 and implicit_value=7 what should be the value of port
>>> after parsing argv?
>>
>> It should be 5.
>>
>> default_value does not matter because the --port option is provided
>> implicit_value does not matter because the --port option includes a value explicitly
>
> Thanks.
>
>>
>>> I am asking because this test
>>> https://github.com/mongodb/mongo/blob/0481c958daeb2969800511e7475dc66986fa9ed5/src/mongo/util/options_parser/options_parser_test.cpp#L753 is failing with boost 1.59 (with boost 1.58 it is passing). Does someone please know what changed in this new version?
>>
>> Does this issue reproduces when using program_options directly? The code above appears to use classes that are
>> similar, but not the same.
>
> I separated boost code. However, this code still fails:
> "
> namespace po = boost::program_options;
>
> po::options_description boostOptions;
> po::positional_options_description boostPositionalOptions;
>
> std::vector<const char*> argv_buffer;
> argv_buffer.push_back("binaryname");
> argv_buffer.push_back("--port");
> argv_buffer.push_back("5");
> int argc = argv_buffer.size();
>
> int style = (((po::command_line_style::unix_style ^
> po::command_line_style::allow_guessing) |
> po::command_line_style::allow_long_disguise) ^
> po::command_line_style::allow_sticky);
>
> std::auto_ptr<po::typed_value<std::string> >
> boostTypeBuilder(po::value<std::string>());
> boostTypeBuilder->implicit_value("7");
>
> std::auto_ptr<po::value_semantic> boostType;
> boostType = boostTypeBuilder;
>
> boostOptions.add_options()("port", boostType.release(), "Port");
> po::command_line_parser(argc, (argc > 0 ? &argv_buffer[0] : NULL)).
> options(boostOptions).
> positional(boostPositionalOptions).
> style(style);.
> run();
> "
>
> What is wrong? Or is this a bug in Boost?

When I try your example, I get the too_many_positional_options_error exception, and it actually seems to be documented
behavior:

        typed_value * implicit_value(const T & v);
        Specifies an implicit value, which will be used if the option is given, but without an adjacent value. Using
        this implies that an explicit value is optional, but if given, must be strictly adjacent to the option, i.e.:
        '-ovalue' or '--option=value'. Giving '-o' or '--option' will cause the implicit value to be applied.

In other words, implicit value is applied here because --port does not have an explicit adjacent value, and then
"5" becomes a superfluous token and result in an error. The documentation say the same in 1.58, and even in 1.50.

The code however, was recently changed, here:

     https://github.com/boostorg/program_options/commit/88dea3c6fdea8c9ea894911897b1770599c383e4
     https://github.com/boostorg/program_options/pull/8

Guess arguments can be made either way how we should handle this. What would you think?

- Volodya


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