我希望能够创建boost::program_options
的选项别名,将其参数存储在相同的键/标签下。
我的软件架构使用不同的专用选项解析器,具体取决于值argv[1]
。但是,有些选项是共享的,例如我的选项--inputs
。
inputOptions.add_options()
("--inputs",
po::value< std::vector<std::string> >()->value_name("paths"),
"List of files to edit.\n");
为了与旧版本的程序兼容,我想在其中一个子解析器中添加一个兼容性选项--input
,将其参数存储在“--inputs”下。理想情况下,该选项最多只能使用一个参数而不是任意多个参数。但是,如果您提供的解决方案使--input
与--inputs
相同,我想也没关系,因为在这种情况下,位置选项仍会发送到“--inputs”。
感谢您的帮助!
答案 0 :(得分:3)
您可以使用extra_parser
(请参阅文档中的Non-conventional syntax),即解析器,可用于在进一步处理令牌之前操纵来自输入的令牌。它可以用于将--run
转换为--command=run
等之类的事情。
Extra解析器是具有以下签名的函子:
std::pair<std::string, std::string>(const std::string &s)
它应该在pair::first
中返回选项名称,并在pair::second
中返回(可选)选项值。 pair::first
为空表示多余的解析器未解析任何内容。值(即pair::second
)可以为空-仅解析了选项名称。如果返回的对有效,则使用名称或名称/值对,而不是通过常规机制来解析原始令牌。
首先,我们编写别名函数:
using OptionAliases = std::map<std::string, std::string>;
std::pair<std::string, std::string>
renameOptions(const std::string &token, const OptionAliases &aliases)
{
auto rtoken(boost::make_iterator_range(token));
// consume "--" prefix
if (!boost::algorithm::starts_with(rtoken, "--")) { return { "", "" }; }
rtoken.advance_begin(2);
// find equal sign (returns iterator range)
const auto eq(boost::algorithm::find_first(rtoken, "="));
// extract option (between "--prefix" and "="/end()) and map it to output
const auto faliases(aliases.find(std::string(rtoken.begin(), eq.begin())));
if (faliases == aliases.end()) { return { "", "" }; }
// return remapped option and (optionally) value after "="
return std::make_pair(faliases->second
, std::string(eq.end(), rtoken.end()));
}
它只是将输入令牌分为--
,name
,=
,value
(如果没有=
符号则没有值)和名称在提供的别名映射中找到它会返回(remapped-name, value)
。
然后,我们使用lambda创建解析器本身:
boost::program_options::ext_parser optionAlias(OptionAliases &&aliases)
{
return [aliases{std::move(aliases)}](const std::string &token)
{
return renameOptions(token, aliases);
};
}
((至少需要C ++ 14,C ++ 11更改为return [aliases](con...
)
您可以将此解析器插入cmdline解析器:
parser.extra_parser(optionAlias({{"mark.twain", "samuel.clemens"}
, {"lewis.caroll", "charles.dodgson"}}));
现在,在上面的示例中,--mark.twain
和--samuel.clemens
都指向vars["samuel.clemens"]
,而--lewis.caroll
和--charles.dodgson
都指向{{1} }。
注意事项:
vars["charles.dodgson"]
样式(前缀为allow_long
的长选项)。可以在代码中更改。--
样式(使用long_allow_adjacent
在一个令牌中允许的值)。也可以在代码中更改。如果有任何非选项令牌都解析为=
,则由于没有上下文,它也将被转换。无法绕开。
示例:如果有一个名称为--alias
的选项期望值并且使用了name
样式,则long_allow_next
将被解析为选项--name=--mark.twain
,其值为{{1 }}(按预期方式),而name
将被解析为选项--mark.twain
,其值为--name --mark.twain
。
简短地说,它可以按预期工作。
希望有帮助。
答案 1 :(得分:2)
您是否尝试过使用po::value<...>(&variable)
表单?解析后,该选项的值将直接保存到变量中。然后,您可以添加指向同一变量的两个选项--input
和--inputs
。此外,您可能必须检查是否只使用了两个选项中的一个,否则会显示错误消息。
我希望我能正确理解你的问题。
答案 2 :(得分:0)
默认情况下,boost :: program_options允许长选项的前缀与该选项匹配。因此,您编写的代码将已经接受--input
作为--inputs
的别名。