boost :: program_options:迭代并打印所有选项

shi*_*iin 13 c++ command-line boost boost-program-options

我最近开始使用boost::program_options并发现它非常方便.也就是说,有一件事遗漏,我无法以一种好的方式编码自己:

我想迭代在a中收集的所有选项,boost::program_options::variables_map以便在屏幕上输出它们.这应该成为一个便利功能,我可以简单地调用列出所有设置的选项,而无需在添加新选项或每个程序时更新功能.

我知道我可以检查并输出各个选项,但如上所述,这应该成为一个对实际选项无视的通用解决方案.我进一步知道我可以迭代内容,variables_map因为它只是一个扩展std::map.然后,我可以检查存储boost::any变量中的类型包含,并使用.as<>它将其转换回适当的类型.但这意味着要编写一个长开关块,每种类型都有一个外壳.对我来说,这看起来不是很好的编码风格.

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

Rig*_*iga 7

正如@Rost之前提到的,访客模式在这里是一个不错的选择.要将其与PO一起使用,您需要为选项使用通知程序,以便在传递选项时,通知程序将填充您的boost::variant值集中的条目.该集应单独存储.之后,您可以迭代您的设置并使用自动处理它们的操作(即打印)boost::apply_visitor.

对于访客来说,继承自 boost::static_visitor<>

实际上,我使访问者和通用方法的使用范围更广.

我创建了一个class MyOption包含描述,boost::variant值和隐式,默认等其他选项的描述.我MyOption按照PO的相同方式填充了该类型的对象的矢量(boost::po::options_add()通过模板).在传球的瞬间std::string()double()boosts::varian牛逼初始化您填写的价值和其他像默认情况下,隐含的类型.

之后我使用Visitor模式来填充boost::po::options_description容器,因为boost::po需要自己的结构来解析输入命令行.在填充过程中,我为每个选项设置了通知器 - 如果它将被通过boost::po将自动填充我的原始对象MyOption.

接下来你需要执行po::parsepo::notify.之后,您将能够使用已填充的std::vector<MyOption*>访问者模式,因为它内部包含boost :: variant.

所有这些都有什么好处 - 你必须在代码中只编写一次你的选项类型 - 填写你的std::vector<MyOption*>.

PS.如果使用这种方法,您将面临为没有值的选项设置notifyer的问题,请参阅此主题以获得解决方案:boost-program-options:notifier用于没有值的选项

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));  
Run Code Online (Sandbox Code Playgroud)


Ros*_*ost 5

使用访客模式是一个很好的例子.不幸的boost::any是不支持访客模式boost::variant.然而,有一些第三方方法.

另一个可能的想法是使用RTTI:创建type_info映射到类型处理程序仿函数的已知类型的映射.