我试图覆盖boost::program_options
中的validate方法,以便解析虚线的ip地址。我还需要在选项前用一个破折号解析参数。为此,我设置了标志po::command_line_style::allow_slash_for_short
。当我添加标志时,验证方法不会被调用。如果我没有设置它工作正常。有人可以指出问题或建议解决方法吗?
这是我的代码:
struct in_addr MCAST_ADDR;
void validate(boost::any& v, const std::vector<std::string>& values, in_addr* target_type, int)
{
printf("validate\n");
std::string const& mcast_addr = boost::program_options::validators::get_single_string(values);
if (!mcast_addr.empty())
if (inet_aton(mcast_addr.c_str(), &MCAST_ADDR) == 0) {
fprintf(stderr, "Invalid address!\n");
}
v = boost::any(MCAST_ADDR);
}
namespace po = boost::program_options;
void parse_args(int argc, char *argv[]) {
try
{
po::options_description desc("Options:");
desc.add_options()
("help,h", "Help screen")
("a", po::value<in_addr>()->required(), "MCAST_ADDR");
po::variables_map vm;
po::store(po::command_line_parser(argc, argv)
.options(desc).
.style(po::command_line_style::allow_slash_for_short) /* the problematic line */
.run(), vm);
po::notify(vm);
}
catch (const po::error &ex) {
std::cerr << ex.what() << '\n';
}
}
int main(int argc, char *argv[]) {
parse_args(argc, argv);
}
答案 0 :(得分:1)
我认为一般问题是您的选项没有简短的名称。是的,&#34;长名&#34;只是一个字符,但这仍然被认为是长名。
要允许将长选项伪装为短选项,请使用allow_long_disguise
。
接下来,要以任何方式允许短选项,您必须决定如何呈现选项参数(--a=value
或--a value
)。
您会发现您未能做出此选择,因为有时库会为您提供运行时诊断。 E.g:
.style(po::command_line_style::allow_long_disguise | po::command_line_style::allow_slash_for_short)
导致:
boost::program_options misconfiguration: choose one or other of 'command_line_style::long_allow_next' (whitespace separated arguments) or 'command_line_style::long_allow_adja cent' ('=' separated arguments) for long options.
现在,解决这个问题的最简单方法就是建立默认行为:
.style(po::command_line_style::default_style
| po::command_line_style::allow_long_disguise
| po::command_line_style::allow_slash_for_short)
现在你可以传递大量的选择:
./a.out /a 239.10.11.12
./a.out /a=239.10.11.12
./a.out -a 239.10.11.12
./a.out -a=239.10.11.12
./a.out --a 239.10.11.12
./a.out --a=239.10.11.12
全部打印
Parsed: 239.10.11.12
让我们使用Boost来解析和验证IP地址!
using ip_address = boost::asio::ip::address;
namespace boost { namespace asio { namespace ip {
void validate(boost::any& v, const std::vector<std::string>& values, ip_address* /*target_type*/, int) {
std::string const& mcast_addr = boost::program_options::validators::get_single_string(values);
auto address = ip_address::from_string(mcast_addr);
if (!address.is_multicast())
throw std::invalid_argument("address not multicast: " + address.to_string());
v = address;
}
} } }
这样,如果我们传递非多播地址,我们会将其标记为错误并报告:
terminate called after throwing an instance of 'std::invalid_argument'
what(): address not multicast: 240.10.11.12
<强> Live On Coliru 强>
#include <boost/asio/ip/address.hpp>
#include <boost/program_options.hpp>
#include <iostream>
using ip_address = boost::asio::ip::address;
namespace boost { namespace asio { namespace ip {
void validate(boost::any& v, const std::vector<std::string>& values, ip_address* /*target_type*/, int) {
std::string const& mcast_addr = boost::program_options::validators::get_single_string(values);
auto address = ip_address::from_string(mcast_addr);
if (!address.is_multicast())
throw std::invalid_argument("address not multicast: " + address.to_string());
v = address;
}
} } }
namespace po = boost::program_options;
int main(int argc, char *argv[]) try {
po::options_description desc("Options:");
desc.add_options()
("help,h", "Help screen")
("a", po::value<ip_address>()->required(), "MCAST_ADDR")
;
po::variables_map vm;
po::store(po::command_line_parser(argc, argv)
.options(desc)
.style(po::command_line_style::default_style
| po::command_line_style::allow_long_disguise
| po::command_line_style::allow_slash_for_short)
.run(), vm);
po::notify(vm);
std::cout << "Parsed: " << vm["a"].as<ip_address>() << std::endl;
} catch (const po::error &ex) {
std::cerr << ex.what() << std::endl;
}
其中还显示了所有测试用例:
+ ./a.out /a 239.10.11.12
Parsed: 239.10.11.12
+ ./a.out /a=239.10.11.12
Parsed: 239.10.11.12
+ ./a.out -a 239.10.11.12
Parsed: 239.10.11.12
+ ./a.out -a=239.10.11.12
Parsed: 239.10.11.12
+ ./a.out --a 239.10.11.12
Parsed: 239.10.11.12
+ ./a.out --a=239.10.11.12
Parsed: 239.10.11.12
和
+ ./a.out /a 240.10.11.12
terminate called after throwing an instance of 'std::invalid_argument'
what(): address not multicast: 240.10.11.12
bash: line 11: 31582 Aborted (core dumped) ./a.out $options
+ ./a.out /a=240.10.11.12
terminate called after throwing an instance of 'std::invalid_argument'
what(): address not multicast: 240.10.11.12
bash: line 11: 31585 Aborted (core dumped) ./a.out $options
+ ./a.out -a 240.10.11.12
terminate called after throwing an instance of 'std::invalid_argument'
what(): address not multicast: 240.10.11.12
bash: line 11: 31587 Aborted (core dumped) ./a.out $options
+ ./a.out -a=240.10.11.12
terminate called after throwing an instance of 'std::invalid_argument'
what(): address not multicast: 240.10.11.12
bash: line 11: 31589 Aborted (core dumped) ./a.out $options
+ ./a.out --a 240.10.11.12
terminate called after throwing an instance of 'std::invalid_argument'
what(): address not multicast: 240.10.11.12