【发布时间】:2017-03-11 08:24:48
【问题描述】:
我有一个程序,它接受一组互斥标志,可用于选择某些行为。假设标志是--csv、--xml 和--json,分别选择CSV、XML 和JSON 作为输出格式。也可以通过使用单个 --format 标志来完成,然后使用 --format=csv、--format=xml 或 --format=json 具有相同的效果,但我不能也不想更改命令行界面.
我已经想出一种方法来检查最多使用其中一个选项,即它们的互斥性。我对此的解决方案不是最漂亮的,但我对这部分没问题。
离开这个检查,我的程序目前看起来像这样。
#include <iostream>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
enum output_formats {format_default, format_csv, format_xml, format_json};
int
main(int argc, char * * argv)
{
auto options = po::options_description{"Options"};
options.add_options()
("csv", "produce output in CSV format")
("xml", "produce output in XML format")
("json", "produce output in JSON format");
auto vm = po::variables_map{};
po::store(po::parse_command_line(argc, argv, options), vm);
po::notify(vm);
// Check that at most one of the options was passed (not shown here).
auto format = format_default;
if (vm.count("csv")) format = format_csv;
else if (vm.count("xml")) format = format_xml;
else if (vm.count("json")) format = format_json;
std::clog << "Output format: " << format << "\n";
}
它正在工作,但我不喜欢 if、else if 级联来确定用户通过的选项(如果有的话)。
我已经看到boost::program_options::bool_switch 允许我定义将设置bool 的标志并且它工作得很好。我想实现enum_switch,这样我就可以将相同的技术应用于我的enum,然后像这样重写代码。
int
main(int argc, char * * argv)
{
auto format = format_default;
auto options = po::options_description{"Options"};
options.add_options()
("csv", enum_switch(&format, format_csv), "produce output in CSV format")
("xml", enum_switch(&format, format_xml), "produce output in XML format")
("json", enum_switch(&format, format_json), "produce output in JSON format");
auto vm = po::variables_map{};
po::store(po::parse_command_line(argc, argv, options), vm);
po::notify(vm);
std::clog << "Output format: " << format << "\n";
}
我在Boost中找到了bool_switch的实现,看起来是这样的。
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
bool_switch(bool* v)
{
typed_value<bool>* r = new typed_value<bool>(v);
r->default_value(0);
r->zero_tokens();
return r;
}
因此,我就这样实现了enum_switch。
template <typename T>
boost::program_options::typed_value<T> *
enum_switch(T * dest, const T value)
{
auto tv = new boost::program_options::typed_value<T>{dest};
tv->default_value(value);
tv->zero_tokens();
return tv;
}
我注意到的第一件事是 Boost 抱怨我的 enum 没有定义 >> 运算符。好的,我定义了一个,结果它永远不会被调用。不幸的是,代码仍然无法按预期工作。如果我在没有选项的情况下调用我的程序,format 将是format_json,如果我通过了,比如--xml,我会收到以下错误:
option '--xml' requires at least one argument
如果我通过--xml 1,我仍然会收到同样的错误,如果我使用--xml=1,我会收到这个有趣的错误:
option '--xml' does not take any arguments
我缺少什么来使用我的enum 显然适用于bool?
【问题讨论】: