I have code like this:
namespace po = boost::program_options;
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("mode1", "")
("mode2", "");
po::variables_map var_map;
po::store(po::parse_command_line(argc, argv, desc), var_map);
po::notify(var_map);
and my program can work only either in mode1 or mode2.
and I don't want syntax like this --mode 0/1
, because of
semantically this is completely different things.
So it will be possible to tell boost program_options module to implement such semantic
no option -> error
mode1 -> ok
mode2 -> ok
mode1 mode2 -> error
?
Note: yes, I can use var_map.count
and check this my self
after po::notify
, but I see classes like these http://www.boost.org/doc/libs/1_59_0/doc/html/boost/program_options/value_semantic.html
in documentation, and I wonder can I use something from program_options to check such semantic.
Note: yes, I can use var_map.count and check this my self after po::notify, but I see classes like these value_semantic in documentation, and I wonder can I use something from program_options to check such semantic.
Mmm. Only so much you can do;
You can use value-semantics to do this during notify:
po::options_description od;
od.add_options()
("mode1", po::bool_switch(&mode1)->notifier([&](bool b) { if (b && mode2) throw po::error{"Only one mode may be specified"}; }))
("mode2", po::bool_switch(&mode2)->notifier([&](bool b) { if (b && mode1) throw po::error{"Only one mode may be specified"}; }))
;
This still requires you to validate that either mode is specified separately:
if (!(mode1 || mode2))
throw po::error("Mode must be specified");
See it Live On Coliru
+ ./a.out
Mode must be specified
+ ./a.out --mode1
mode1: true mode2: false
+ ./a.out --mode2
mode1: false mode2: true
+ ./a.out --mode1 --mode2
Only one mode may be specified
+ ./a.out --mode2 --mode1
Only one mode may be specified
You could do without the notifiers above and simple write the constraint as a NXOR:
if (mode1 == mode2)
throw po::error("Exactly 1 of --mode1 and --mode2 must be specified");
See it Live On Coliru
You could of course have all options result in a custom type and make the notifiers aware of the logic.
I'll try to demo this. Update: This is a dead end since all value semantics imply an (optional) argument. This at the very least makes things ugly.
I was thinking along there lines: http://coliru.stacked-crooked.com/a/a7bd9072f3fa024e
enum class Mode {
mode1 = 1,
mode2 = 2
};
using mode_select = boost::optional<Mode>;
mode_select mode;
po::options_description od;
od.add_options()
("mode1", po::value<mode_select>(&mode)->implicit_value(Mode::mode1, ""))
("mode2", po::value<mode_select>(&mode)->implicit_value(Mode::mode2, ""))
;
As you can see, things don't quite work out the way I'd like them to
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With