29

One can use notifier for parsed options only if they have value_semantic. What is the best way for no-value options to be automatically handled by the given notifier?

The simple approach is to make a dummy value_semantic with implicit assignment, so a user can pass the option without a value. This leads to a possibility of explicitly provided values. One can add a run-time check if the value was provided and throw an error.

Update: BUT, this doesn't work in presence of positional options, because a positional option's value can follow no-value option raising an exception as s given value to it.

Riga
  • 2,099
  • 1
  • 19
  • 27

3 Answers3

46

One guy OXPEHOMETP on a russian programmers forum gave me a pice of advice to use boost::program_options::bool_switch().

When defining an option with no value via value-permitted interface, one must pass not boost::program_options::typed_value() as semantics, but bool_switch(). This means that no value can be explicitly taken for this option from the command line. One can find info about it at http://www.boost.org/doc/libs/release/doc/html/boost/program_options/bool_switch.html

Riga
  • 2,099
  • 1
  • 19
  • 27
  • 24
    Example usage of bool_switch: ```("normalize_regularizer,n", po::bool_switch()->default_value(false), "Normalize regularization constant")``` – jhclark Jan 11 '13 at 18:01
  • 1
    Surprisingly, I didn't find it covered in boost.po documentation. Thank you! – berkus Nov 11 '13 at 11:32
29

This is full example on providing a flag as an option to complement current answers:

#include <iostream>

#include <boost/program_options.hpp>

using namespace std;

namespace po = boost::program_options;


int main(int ac, char* av[])
{
    po::options_description desc("Allowed options");

    desc.add_options()
        ("help", "produce help message")
        ("overwrite,o", po::bool_switch()->default_value(false),
                        "enable file overwrite");

    po::variables_map vm;
    po::store(po::parse_command_line(ac, av, desc), vm);

    boolalpha(cout);  // display true and false for bool
    cout << "overwrite is: " << vm["overwrite"].as<bool>() << endl;

    return 0;
}

Mine qmake pro file (I use Qt 5.4):

TEMPLATE = app
CONFIG += console
CONFIG += c++14
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp


include(deployment.pri)
qtcAddDeployment()

INCLUDEPATH += /opt/boost_1_57_0

unix:!macx: LIBS += -L/opt/boost_1_57_0/stage/lib -lboost_program_options

Running the program without any options results in:

./untitled4
overwrite is: false

However running with '-o' option/flag gives:

./untitled4 -o
overwrite is: true
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • 3
    and if not obvious, program option's bool_switch(), like value() optionally takes a pointer to a variable to hold the value (which for bool_switch() would be type bool) so assuming e.g. `bool clobber;` declared beforehand you could have `("overwrite,o", po::bool_switch(&clobber)->default_value(false), "enable file overwrite");` – Chip Grandits Feb 07 '17 at 17:31
1

Use the zero_tokens modifier. It seems you also need to use implicit_value, but anything provided after the option name won't be consumed by the option parser. Instead, when the option is noticed on the command line, the implicit value will be assigned to the option, triggering the option's notifier (so make sure to provide a notifier function). Apparently, it's also important for the option's value type to be string. I'm not clear on why.

void got_foo(std::string const&);

desc.add_options()
  ("foo", 
   po::value<std::string>()
     ->implicit_value("")
     ->zero_tokens()
     ->notifier(&got_foo),
   "foo description")
;
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Yes, that was my initial approach. But if I have a positional option after a passed key it must be filled by got_foo properly. This is tricky and not clean, makes undesirable relations between distinct options based on some technical problem. – Riga Aug 30 '11 at 09:09
  • I don't understand. When I pass a non-option after `--foo` on my test command line, its value is not stored in the option value for `foo`. The `foo` option gets the value `""` because that's what its implicit value is. – Rob Kennedy Aug 30 '11 at 13:41
  • you misunderstand `implicit_value()` option, it works only if no value provided, but then some value follow the key it is used instead of implicit value. So value of next passed positional option will be used as our non-value option's value. Look: `my_program -key_with_no_value positional_option_value` . Here `positional_option_value` will be treated as `key_with_no_value`'s passed value in `implicit_value()` approach – Riga Aug 30 '11 at 15:06