Boost程序选项解析枚举位掩码



我的程序有一组可能发生的可恢复错误,我们称它们为ErrorAErrorBErrorC。对于这些错误中的任何一个,我的程序可以忽略它们(因为它们是可恢复的(,也可以终止,后者是默认行为。现在,我希望用户指定是否应该忽略这些错误。这应该通过命令行参数--ignore来实现,后面跟着应忽略的错误名称。例如:

./MyProgram --ignore ErrorA ErrorC

在代码中,我使用单个位掩码枚举表示这些错误类别:

enum class IgnoreErrors {
None = 0, //Ignore no errors
ErrorA = 1 << 0,
ErrorB = 1 << 1,
ErrorC = 1 << 2
};

我正在使用boost::program_options,并试图将--ignore选项添加到options_description中,如下所示:

value<IgnoreErrors>()->multitoken()->default_value(IgnoreErrors::None)

这需要我为IgnoreErrors提供一个operator>>的实现,而这正是我陷入困境的地方。我试过这个:

istream& operator>>(istream& in, IgnoreErrors& err) {
//Assumption: 'in' contains ALL tokens passed to the --ignore flag
err = IgnoreErrors::None; //Needed to make |= work
string token;
while(getline(in, token, ' ')) {
err |= ignore_error_from_str(token);    
}
return in;
}

这将正确地将一个或多个令牌解析为一个IgnoreErrors值,但之后我的程序将失败:the argument ('ErrorA ErrorC') for option '--ignore' is invalid。有趣的是,如果我使用in >> token而不是getline,我只会得到第一个令牌(ErrorA(。

如果我将operator>>的实现更改为将单个令牌解析为单个IgnoreError值,并将options_description更改为使用value<vector<IgnoreErrors>>(),Boost将不再识别IgnoreErrorsoperator>>,而是查找vector<IgnoreErrors>的实现。然而,我必须手动将这个向量折叠成一个单独的IgnoreErrors值,这似乎很奇怪。我想了解处理这种情况的"预期"方式是什么。

如何使用boost::program_options将多令牌参数解析为单个值?

所以我找到了一种合理的方法来完成这项工作。可以使用自定义验证器,而不是提供operator>>,如下所示:

void validate(boost::any &v, const std::vector<std::string> &all_tokens,
IgnoreErrors *target_type, int) {
validators::check_first_occurrence(v);
std::vector<std::string> tokens;
boost::algorithm::split(tokens,
validators::get_single_string(all_tokens),
boost::is_any_of(" "));
auto ignore_errors = IgnoreErrors::None;
for (auto &token : tokens) {
ignore_errors |= ignore_error_from_str(token);
}
v = boost::any(ignore_errors);
}

有些事情对我来说并不那么明显:

  • 在我的例子中,validators::get_single_string(all_tokens)的结果是"ErrorA ErrorC",所以我不得不手动将这个字符串拆分为多个令牌
  • validate函数的专用化必须与它专用的类型(在我的例子中为IgnoreErrors(在同一个命名空间中

最新更新