boost :: program_options位置选项

时间:2016-05-05 22:07:02

标签: c++ boost boost-program-options

我有一个位置选项(文件名),我希望它是最后一个选项。基本上,用户可以在命令行上传递一堆东西,并且还使用-F作为文件名。但是,我希望用户也能够将文件名放在最后。

例如

./program --var 3 /path/to/file

我目前实现的代码允许调用者将文件名放在命令行的任何位置。无论如何,强迫位置参数总是在"常规"之后。的?

以下是我如何设置位置参数:

pos_opts_desc.add("filename", -1);

并解析命令行:

store(
    command_line_parser(argc, argv).options(opts_desc).postional(pos_opts_desc).run(),
    opts_var_map);

提前感谢您的帮助。

编辑添加:

我完全可以在命令行的任何地方指定-F。但是,如果设置是通过位置选项完成的,我想确保位置选项位于最后。

2 个答案:

答案 0 :(得分:6)

run()成员函数会返回一个类型为parsed_options的实例。简单的用法是永远不要实际查看此对象并将其直接传递到store(),如您的示例所示:

po::store(
    po::command_line_parser(argc, argv).options(opts_desc).postional(pos_opts_desc).run(),
    opts_var_map);

但我们可以抓住它并检查其内容:

auto parsed = po::command_line_parser(argc, argv)
    .options(opts_desc)
    .postional(pos_opts_desc)
    .run();
po::store(parsed, opts_var_map);

parsed_options类有一个成员options,其中包含所有选项的有序列表(与变量映射不同,后者按选项名称排序 - 因为它是一个std::map)。因此,您可以查找"filename"参数并检查其position_key成员。我们要么:position_key == -1(这意味着它提供了-F)或position_key == 0,它是选项列表中的最后一个元素(它是一个位置参数,是最后一个参数):

auto it = std::find_if(parsed.options.begin(), parsed.options.end(),
    [](po::option const& o){ return o.string_key == "filename"; });
if (it == parsed.options.end()) {
    // fail: missing filename);
}
if (it->position_key != -1 && it != std::prev(parsed.options.end())) {
    // fail: filename was positional but wasn't last
}

答案 1 :(得分:3)

variables_map顾名思义是std::map,它允许我们在其上使用常规STL函数。

    if ( vm.count("filename") ) {
      if ( vm.find("filename") != std::prev(vm.rbegin()).base() ) {
        std::cout << "filename must go at the end.";
      }
    }

测试用例:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp -lboost_system -lboost_program_options \
&& echo -n "Case 1 " && ./a.out asdf --foo=12 && echo \
&& echo -n "Case 2 " && ./a.out --foo=12 asdf && echo \
&& echo -n "Case 3 " && ./a.out asdf && echo \
&& echo -n "Case 4 " && ./a.out --foo=12 && echo \
&& echo -n "Case 5 " && ./a.out && echo \
&& echo -n "Case 6 " && ./a.out --foo=12 asdf asdf

结果:

Case 1 filename must go at the end.
Case 2 
Case 3 
Case 4 
Case 5 
Case 6 option '--filename' cannot be specified more than once