Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost::program_选项:迭代并打印所有选项_C++_Boost_Command Line_Boost Program Options - Fatal编程技术网

C++ boost::program_选项:迭代并打印所有选项

C++ boost::program_选项:迭代并打印所有选项,c++,boost,command-line,boost-program-options,C++,Boost,Command Line,Boost Program Options,我最近开始使用boost::program_options,发现它非常方便。这就是说,有一件事我没能以一种好的方式为自己编码: 我想迭代在boost::program\u options::variables\u map中收集的所有选项,以便在屏幕上输出它们。这应该成为一个方便的函数,我可以简单地调用它列出所有设置的选项,而无需在添加新选项或为每个程序更新函数 我知道我可以检查并输出单个选项,但如上所述,这应该成为一个通用解决方案,而不考虑实际选项。我还知道我可以迭代变量\u map的内容,因为

我最近开始使用
boost::program_options
,发现它非常方便。这就是说,有一件事我没能以一种好的方式为自己编码:

我想迭代在
boost::program\u options::variables\u map
中收集的所有选项,以便在屏幕上输出它们。这应该成为一个方便的函数,我可以简单地调用它列出所有设置的选项,而无需在添加新选项或为每个程序更新函数

我知道我可以检查并输出单个选项,但如上所述,这应该成为一个通用解决方案,而不考虑实际选项。我还知道我可以迭代
变量\u map
的内容,因为它只是一个扩展的
std::map
。然后,我可以检查存储的
boost::any
变量中包含的类型,并使用
.as
将其转换回适当的类型。但这意味着编码一个长的开关块,每种类型有一个外壳。在我看来,这不是一种好的编码风格


所以问题是,有没有更好的方法迭代这些选项并输出它们?

使用访问者模式是一个很好的例子。不幸的是,
boost::any
不支持像
boost::variant
那样的访问者模式。不过也有一些第三方


另一个可能的想法是使用RTTI:创建映射到类型处理函数的已知类型的
type\u info
映射。

正如@Rost前面提到的,访客模式是一个很好的选择。要与PO一起使用,您需要为您的选项使用通知程序,这样,如果选项被传递,通知程序将在您的
boost::variant
值集中填充一个条目。该设备应单独存放。之后,您可以在集合上迭代,并使用
boost::apply\u visitor
自动处理操作(即打印)

对于访问者,从
boost::static\u访问者继承

实际上,我使访问者和通用方法的使用更加广泛

我创建了一个
类MyOption
,其中包含value和其他选项(如implicit、default等)的description、
boost::variant
。我通过模板填充
MyOption
类型的对象向量,方法与PO do一样(请参见
boost::PO::options\u add()
)。在传递
std::string()
double()
for
boosts::varian
t初始化时,您将填充值的类型和其他内容,如默认值、隐式值

之后,我使用访问者模式填充
boost::po::options\u description
容器,因为
boost::po
需要自己的结构来解析输入命令行。在填充过程中,我为每个选项设置notifyer-如果它将被传递
boost::po
将自动填充我的原始对象
MyOption

接下来需要执行
po::parse
po::notify
。之后,您将能够通过访问者模式使用已经填充的
std::vector
,因为它内部包含boost::variant

在填充
std::vector
时,所有这些都有什么好处?只需在代码中编写一次选项类型

注意:如果使用这种方法,您将面临为没有值的选项设置notifyer的问题,请参阅本主题以获得解决方案:

PS2。代码示例:

std::vector<MyOptionDef> options;
OptionsEasyAdd(options)
  ("opt1", double(), "description1")
  ("opt2", std::string(), "description2")
...
;
po::options_descripton boost_descriptions;
AddDescriptionAndNotifyerForBoostVisitor add_decr_visitor(boost_descriptions);
// here all notifiers will be set automatically for correct work with each options' value type
for_each(options.begin(), options.end(), boost::apply_visitor(add_descr_visitor));  
std::向量选项;
选项SEASYADD(选项)
(“opt1”,double(),“description1”)
(“opt2”,std::string(),“description2”)
...
;
po::选项描述和增强描述;
AddDescription和NotifyerForBoostVisitor添加描述访问者(增强描述);
//在这里,所有通知程序将自动设置为使用每个选项的值类型进行正确工作
对于每个(options.begin()、options.end()、boost::apply_visitor(add_descr_visitor));

我今天正处理这类问题。这是一个老生常谈的问题,但也许这会帮助那些正在寻找答案的人

我提出的方法是尝试一组as(),然后忽略异常。虽然不太漂亮,但我还是让它发挥作用了

在下面的代码块中,vm是来自boost程序选项的变量映射。vit是vm上的迭代器,使其成为一对std::string和boost::program_options::variable_value,后者是boost::any。我可以用vit->first打印变量名,但是vit->second不太容易输出,因为它是boost::any,即原始类型已丢失。有些应该转换为std::string,有些应该转换为double,依此类推

因此,要计算变量的值,我可以使用以下公式:

std::cout << vit->first << "=";
try { std::cout << vit->second.as<double>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<int>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<std::string>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<bool>() << std::endl;
} catch(...) {/* do nothing */ }

std::cout first由于您将只打印它们,所以在解析时可以获取原始字符串表示形式。(代码中可能有编译器错误,我从代码库中删除了它,并取消了类型定义)

std::vector GetArgumentList(const std::vector&raw)
{
std::向量args;
BOOST\u FOREACH(常量BOOST::程序选项::选项和选项,原始)
{
如果(option.unregisted)继续;//跳过未知选项
if(option.value.empty())
args.push_back(“--”+option.string_key));
其他的
{
//这将丢失位置选项的顺序
BOOST_FOREACH(const std::string&value,option.value)
{
args.push_back(“--”+option.string_key));
参数。推回(值);
}
}
}
返回args;
}
用法:

boost::program_options::parsed_options parsed = boost::program_options::command_line_parser( ...

std::vector<std::string> arguments = GetArgumentList(parsed.options);
// print
boost::program\u options::parsed\u options parsed=boost::program\u options::command\u line\u parser(。。。
std::vector arguments=GetArgumentList(parsed.options);
//印刷品

感谢您提供有关RTTI的链接和想法。我希望我可以阻止构建结构
boost::program_options::parsed_options parsed = boost::program_options::command_line_parser( ...

std::vector<std::string> arguments = GetArgumentList(parsed.options);
// print