【问题标题】:invalid option value exception using boost program-options使用 boost 程序选项的无效选项值异常
【发布时间】:2011-02-25 17:09:36
【问题描述】:

我有一个使用 boost v1.45.0 程序选项的 Visual Studio 2008 C++ 应用程序。

我希望能够解析如下所示的命令行选项:foo.exe -x 1,2, 4-7,这样它会生成具有值 [1、2、4、5、6、7] 的 std::vector< int >。所以,我写了一个自定义验证器:

typedef std::vector< int > IDList;

void validate( boost::any& v, const std::vector< std::string >& tokens, IDList*, int )
{
    // Never gets here
}

int _tmain( int argc, _TCHAR* argv[] )
{
    IDList test_case_ids;

    po::options_description desc( "Foo options" );
    desc.add_options()
        ("id,x", po::value< IDList >(), "Specify a single ID or a range of IDs as shown in the following command line: foo.exe -x10,12, 15-20")
    ;

    po::variables_map vm;

    try
    {
        po::store( po::parse_command_line( argc, argv, desc ), vm );
        po::notify( vm );
    }
    catch( const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        std::cout << desc << std::endl;
        return 1;
    }

    return 0;
}

但是,我从来没有得到我的自定义验证器代码。我总是在parse_command_line 收到异常消息:in option 'id': invalid option value

我需要做些什么才能使这项工作如愿以偿?

谢谢, 保罗H

【问题讨论】:

  • 运行时给它的命令行是什么?
  • BTW -- 你是否使用 UNICODE 编译...在这种情况下你需要使用库操作的 wstring 版本。
  • @Dennis - 命令行是foo.exe -x 1,2, 4-7。是的,我正在使用 UNICODE 标志进行编译。更改为 std::wstring 不会更改结果。我得到了同样的例外。

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


【解决方案1】:

作为boost::program_options::value_semantic 的typedef std::vector&lt;int&gt; 不能按照您希望的方式工作,因为vector 在程序选项库中有一个special meaning

库提供特殊支持 对于向量 - 将有可能 多次指定选项,并且 将收集所有指定的值 在一个向量中。

意思是这样的描述

typedef std::vector< int > IDList;
po::options_description desc( "Foo options" );
desc.add_options()
    ("id,x", po::value< IDList >(), "list of IDs")
;

在给定以下命令行的情况下合并为单个 std::vector&lt;int&gt;

a.out --id 1 --id 2 --id 3 --id 4

结果将是一个包含四个元素的std::vector。您需要定义一个特定的类型来使用自定义验证器,struct IDListcorrect approach

【讨论】:

  • 您是说在这种情况下 type(def) IDList 是“魔术”吗?即它必须命名为 IDList 而不是别的什么?
【解决方案2】:

您可以尝试编写自己的函数来解析命令行选项:

See here

您编写自己的解析器函数,例如reg_foo,并按如下方式使用:

variables_map vm;
store(command_line_parser(argc, argv).options(desc).extra_parser(reg_foo)
          .run(), vm);

另请参阅在 example/custom_syntax.cpp 中与 boost 一起分发的示例代码

【讨论】:

  • 我想我可以这样做,但我只需要 -x 选项的自定义解析器。我以为这就是自定义验证器的用途?
【解决方案3】:

问题是IDList 的定义。如果我更改定义以匹配regex.cpp 示例中使用的magic_number 类型,它就可以工作。

struct IDList
{
public:
    std::vector< int > ids_;
    IDList( std::vector< int > ids ) : ids_( ids ) {}
};

我还没有调查为什么 typedef 对框架来说是个问题,但这是可行的。

-保罗赫

【讨论】:

  • 如果我 2 天不能接受,让我发布答案有什么意义?
  • 鼓励其他答案,您不会通过回答自己的问题获得代表。
  • @Sam - 我不清楚。我的意思是,“如果我 2 天都不能将其标记为答案,为什么还要让我发布答案?”。
猜你喜欢
  • 1970-01-01
  • 2014-10-22
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多