Opened 15 years ago

Closed 12 years ago

#1132 closed Bugs (fixed)

zero_tokens doesn't work

Reported by: Bryan Green <bgreen0@…> Owned by: Vladimir Prus
Milestone: Boost 1.36.0 Component: program_options
Version: Boost 1.34.1 Severity: Problem
Keywords: Cc: bgreen@…

Description

In the documentation for program_options, under the "Library Overview"/"Syntactic Information", the documentation appears to be incorrect.

For the following option description:

    ("verbose", value<string>()->zero_tokens(), "verbosity level")

It states that:

"the user may either provide a single token for the value, or no token at all."

I wrote a test program based on the options given in this section of the manual, and I get different behavior for the 'verbose' option. In fact, the actual behavior is almost intuitive: the option is unusable. No matter what you do, its an error. Seems natural since you're saying the option has a value associated with it, yet no tokens may be given to specify the value.

It also turns out that 'multitoken()' does not allow you to pass multiple tokens, but it does raise an exception if you specify anything after the first value, i.e.:

./a.out --email blah@blah me@somewhere
exception: in option 'email': multiple values not allowed

./a.out --email blah@blah --help   
exception: in option 'email': multiple values not allowed

Here's my test program:

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

using namespace boost::program_options;
using namespace std;

int main(int argc,char *argv[])
{
    options_description desc;
    desc.add_options()
        ("help", "produce help message")
        ("compression", value<string>(), "compression level")
        ("verbose", value<string>()->zero_tokens(), "verbosity level")
        ("email", value<string>()->multitoken(), "email to send to")
        ;

    variables_map vm;
    try {
        store(parse_command_line(argc, argv, desc), vm);
        notify(vm);    
    } catch (exception &e) {
        cout << "exception: " << e.what() << endl;
        return -1;
    }

    if (vm.count("help"))
        cout << desc << endl;

    if (vm.count("compression"))
        cout << "compression " << vm["compression"].as<string>() << endl;

    if (vm.count("verbose"))
        cout << "verbose " << vm["verbose"].as<string>() << endl;

    if (vm.count("email"))
        cout << "email " << vm["email"].as<string>() << endl;

    return 0;
}

Change History (12)

comment:1 by crazykriz@…, 15 years ago

Can (still) verify this bug who seems to be rather old, because even in Boost 1.31.x I couldn't use the zero_tokens() option. I wrote an email to Vladimir Prus but never got an answer.

I hope this mess will be fixed in near future.

comment:2 by Vladimir Prus, 15 years ago

For the record, using words like "mess" is not likely to get any fix sooner :-P

in reply to:  2 comment:3 by crazykriz@…, 15 years ago

Replying to vladimir_prus:

For the record, using words like "mess" is not likely to get any fix sooner :-P

Don't mind, "mess" wasn't related to your work (which is excellent), but related to the situation ;-) But, do you know what's going wrong with zero_tokens() and multitokens()?

comment:4 by Vladimir Prus, 15 years ago

Type: Support RequestsBugs

comment:5 by Vladimir Prus, 14 years ago

Milestone: To Be DeterminedBoost 1.36.0
Summary: program_options documentation error.zero_tokens clarification

comment:6 by grywacz@…, 14 years ago

The bug (at least for zero_tokens) is still there - verified with 1.34 and 1.37.

comment:7 by grywacz@…, 14 years ago

Summary: zero_tokens clarificationzero_tokens doesn't work

The simplest program to test with:

#include <boost/program_options.hpp> #include <iostream> #include <string> using namespace std; namespace po = boost::program_options; int main(int argc, char *argv[]) {

po::options_description desc("test"); desc.add_options()

("server", po::value<std::string>()->zero_tokens());

po::variables_map vm;

po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);

}

comment:8 by anonymous, 13 years ago

The problem with multitoken is still there in Boost 1.40 :-(

./a.out --email blah@blah me@somewhere
exception: in option 'email': multiple values not allowed

I could use value<vector<string> >(), but this implies that the option can occur more than one time on command line which I don't want allow in my case.

zero_token() also broken, I always get:

exception: in option 'verbose': at least one value required

comment:9 by s.ochsenknecht@…, 13 years ago

I looked a bit deeper to the zero_token() issue. I found out that there is implicit_value(...) function which can be used for this feature. If an option occurs without any further tokens and this option is allowed to stay without any arguments, then this implicit value is assign:

    options_description desc;
    desc.add_options()
        ("verbose", value< int >()->implicit_value(1), "verbosity level")
        ;

Anyhow documentation has to be updated and maybe the zero_tokens() function needs to be removed. The multitoken() issue is still open.

Please comment. Thanks.

comment:10 by Vladimir Prus, 13 years ago

Another way how zero_tokens is used to good effect is the 'bool_switch' function:

BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* bool_switch(bool* v) {

typed_value<bool>* r = new typed_value<bool>(v); r->default_value(0); r->zero_tokens();

return r;

}

This, together with validator for the bool types, allows to make --whatever be interpreted as 'true' value for 'whatever' option. Note this code:

BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs,

bool*, int)

{

check_first_occurrence(v); string s(get_single_string(xs, true));

The 'true' passed to 'get_single_string' means that if there are no tokens, the empty string should be returned -- which is then interpreted as true value.

Therefore, 'zero_tokens' makes sense exclusively when the validator for the type handles empty string or 'implied_value' is also specified. Seems like purely documentation bug to me, then.

comment:11 by calum.mitchell@…, 12 years ago

I ran into this problem when reading the documentation for 1.45.0 and trying to compile/run the example code.

The resolution appears to be:

desc.add_options()

("help", "produce help message")
("compression", value<string>(), "compression level")
("verbose", value<string>()->implicit_value("0"), "verbosity level")
("email", value<vector<string>>()->multitoken(), "email to send to")
;

As mentioned in an earlier comment, the use of value<vector<string>>() for a multitoken() option means that the option can occur more than one time on the command line.

comment:12 by Vladimir Prus, 12 years ago

Resolution: fixed
Status: newclosed

(In [67774]) Clarify docs for 'zero_token'. Fixes #1132.

Note: See TracTickets for help on using tickets.