boost program_options: using zero-parameter option

2019-02-25 14:02发布

问题:

I am wondering whether it is possible to use zero-parameter options multiple times with boost::program_options.

I have something in mind like this:

mytool --load myfile --print_status --do-something 23 --print_status

It is easy to get this working with one "print_status" parameter, but it is not obvious to me how one could use this option two times (in my case, boost throws an exception if a zero-parameter option is specified more than once).

So, the question is:

Is there any (simple) way to achieve this with out-of-the box functionality from program_options?

Right now, it seems this is a drawback of the current program_options implementation.

P.S.:

There have already been similar questions in the past (both over four years old), where no solution was found:

http://lists.boost.org/boost-users/2006/08/21631.php

http://benjaminwolsey.de/de/node/103

This thread contains a solution, but it is not obvious whether it is a working one, and it seems rather complex for such a simple feature:

Specifying levels (e.g. --verbose) using Boost program_options

回答1:

If you don't need to count the number of times the option has been specified, it's fairly easy (if a little odd); just declare the variable as vector<bool> and set the following parameters:

std::vector<bool> example;
// ...
desc.add_options()
    ("example,e",
     po::value(&example)
     ->default_value(std::vector<bool>(), "false")
     ->implicit_value(std::vector<bool>(1), "true")
     ->zero_tokens()
    )
// ...

Specifying a vector suppresses multiple argument checking; default_value says that the vector should by default be empty, implicit_value says to set it to a 1-element vector if -e/--example is specified, and zero_tokens says not to consume any following tokens.

If -e or --example is specified at least once, example.size() will be exactly 1; otherwise it will be 0.

Example.

If you do want to count how many times the option occurs, it's easy enough to write a custom type and validator:

struct counter { int count = 0; };
void validate(boost::any& v, std::vector<std::string> const& xs, counter*, long)
{
    if (v.empty()) v = counter{1};
    else ++boost::any_cast<counter&>(v).count;
}

Example.

Note that unlike in the linked question this doesn't allow additionally specifying a value (e.g. --verbose 6) - if you want to do something that complex you would need to write a custom value_semantic subclass, as it's not supported by Boost's existing semantics.



标签: c++ boost