boost-program-options: notifier for options with no value
Asked Answered
R

3

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.

Rhodos answered 24/8, 2011 at 11:36 Comment(0)
R
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

Rhodos answered 1/9, 2011 at 22:14 Comment(2)
Example usage of bool_switch: ("normalize_regularizer,n", po::bool_switch()->default_value(false), "Normalize regularization constant")Plummy
Surprisingly, I didn't find it covered in boost.po documentation. Thank you!Orjonikidze
C
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
Collation answered 25/1, 2015 at 4:32 Comment(1)
and if not obvious, program option's bool_switch(), like value<T>() 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");Reporter
W
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")
;
Wheelbase answered 29/8, 2011 at 23:57 Comment(3)
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.Rhodos
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.Wheelbase
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() approachRhodos

© 2022 - 2024 — McMap. All rights reserved.