使用 boost::program_options 禁止无符号值的负参数
Disallow negative argument for unsigned value with boost::program_options
假设我有一个程序使用 boost::program_options 来解析命令行参数,其中一个程序有一个 unsigned
值:
#include <boost/program_options.hpp>
#include <iostream>
namespace po = boost::program_options;
int main(int argc, char* argv[]) {
unsigned num;
po::options_description desc;
desc.add_options()
("num,n", po::value<unsigned>(&num), "Non-negative number");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
std::cout << "Number: " << num << '\n';
return 0;
}
然后,如果我在命令行上传递一个负值,它会接受它并将其环绕:
$ ./bponeg -n -1
Number: 4294967295
我宁愿负数触发错误(即抛出 invalid_option_value
),就像我写 ./bponeg -n abc
一样。
从我自己解析后的代码来看,似乎无法区分用户是写 -1
还是写 4294967295
.
我可以指示 program_options 解析器拒绝 unsigned
值的负输入吗?
你可以写一个custom validator,就像这样:
struct nonnegative {
unsigned value;
};
void validate(boost::any& v, const std::vector<std::string>& values, nonnegative*, int)
{
using namespace boost::program_options;
validators::check_first_occurrence(v);
std::string const& s = validators::get_single_string(values);
if (s[0] == '-') {
throw validation_error(validation_error::invalid_option_value);
}
v = lexical_cast<unsigned>(s);
}
然后只需使用 nonnegative
而不是 unsigned
。
但我认为只使用 int64_t
并在它为负数时抛出错误会更容易。代码也更少。
假设我有一个程序使用 boost::program_options 来解析命令行参数,其中一个程序有一个 unsigned
值:
#include <boost/program_options.hpp>
#include <iostream>
namespace po = boost::program_options;
int main(int argc, char* argv[]) {
unsigned num;
po::options_description desc;
desc.add_options()
("num,n", po::value<unsigned>(&num), "Non-negative number");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
std::cout << "Number: " << num << '\n';
return 0;
}
然后,如果我在命令行上传递一个负值,它会接受它并将其环绕:
$ ./bponeg -n -1 Number: 4294967295
我宁愿负数触发错误(即抛出 invalid_option_value
),就像我写 ./bponeg -n abc
一样。
从我自己解析后的代码来看,似乎无法区分用户是写 -1
还是写 4294967295
.
我可以指示 program_options 解析器拒绝 unsigned
值的负输入吗?
你可以写一个custom validator,就像这样:
struct nonnegative {
unsigned value;
};
void validate(boost::any& v, const std::vector<std::string>& values, nonnegative*, int)
{
using namespace boost::program_options;
validators::check_first_occurrence(v);
std::string const& s = validators::get_single_string(values);
if (s[0] == '-') {
throw validation_error(validation_error::invalid_option_value);
}
v = lexical_cast<unsigned>(s);
}
然后只需使用 nonnegative
而不是 unsigned
。
但我认为只使用 int64_t
并在它为负数时抛出错误会更容易。代码也更少。