c ++ / boost program_options一个选项禁用其他

时间:2015-11-13 20:20:50

标签: c++ c++11 boost

我有这样的代码:

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);

我的程序只能在mode1或mode2中工作。 而且我不想要像--mode 0/1这样的语法,因为 从语义上讲,这是完全不同的事情。

因此可以告诉boost program_options 模块实现这种语义

没有选项 - >错误

mode1 - >确定

mode2 - >确定

mode1 mode2 - >错误

注意:是的,我可以使用var_map.count并自行查看 在po::notify之后,我看到类似http://www.boost.org/doc/libs/1_59_0/doc/html/boost/program_options/value_semantic.html的类 在文档中,我想我可以使用program_options中的内容来检查这种语义。

1 个答案:

答案 0 :(得分:6)

  

注意:是的,我可以使用var_map.count并在po :: notify之后检查这个我自己,但我在文档中看到类似于value_semantic的类,我想我可以使用program_options中的某些东西来检查这种语义。

嗯。只有你能做的那么多;

自定义通知程序

您可以使用值语义在 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"}; }))
    ;

这仍然要求您验证是否单独指定了任一模式:

if (!(mode1 || mode2))
    throw po::error("Mode must be specified");

查看 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

手动验证

你可以不使用上面的通知符,简单地将约束写为NXOR:

if (mode1 == mode2)
    throw po::error("Exactly 1 of --mode1 and --mode2 must be specified");

查看 Live On Coliru

的Hightech

当然,您可以将所有选项都生成自定义类型,并使通知程序了解逻辑。

我会尝试演示这个。更新:这是一个死胡同,因为所有的值语义都暗示了一个(可选的)参数。这至少会使事情变得丑陋。

我一直在思考: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, ""))
        ;

正如你所看到的,事情并没有像我希望的那样完成