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

Posted

技术标签:

【中文标题】c++/boost program_options 一个选项禁用其他【英文标题】:c++/boost program_options one option disable other 【发布时间】:2015-11-13 20:20:49 【问题描述】:

我有这样的代码:

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

而我的程序只能在模式 1 或模式 2 中运行。 我不想要像--mode 0/1 这样的语法,因为 从语义上讲,这是完全不同的事情。

所以可以告诉 boost program_options 实现这种语义的模块

没有选项 -> 错误

mode1 -> 好的

模式2 -> 好的

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 中的一些东西来检查这种语义。

【问题讨论】:

在this example他们似乎使用var_map的检查方法。 【参考方案1】:

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

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

自定义通知器

您可以在期间通知使用值语义来执行此操作:

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

高科技

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

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

我是这样想的: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, ""))
        ;

如您所见,事情并没有像我希望的那样发展

【讨论】:

非常感谢您提供如此详细的回答。

以上是关于c++/boost program_options 一个选项禁用其他的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::program_options 打印普通和位置参数的帮助

boost::program_options - 解析多个命令行参数,其中一些是字符串,包括空格和字符

Boost.Program_Options:当 <bool> 被指定为命令行选项时,啥是有效的命令行参数?

boost库中的 program_options

未定义的引用`boost :: program_options :: options_description :: m_default_line_length'

Boost 链接问题 - 多个版本