我需要能够boost::program_options
解析一系列双精度数
在命令行上传递的。对于积极的双打,这没有问题,
当然(在add_options中使用带有std::vector<double>
的多重声音),但是
消极的,我知道这些都是含糊不清的论点。
以下是我想要介绍的内容:
mycommand --extent -1.0 -2.0 -3.0 1.0 2.0 3.0 --some-other-argument somevalue
extent 由具有至少一个构造函数的Bounds
类支持
它包含六个单独的T
个参数(在本例中为double
)。
template <typename T>
class Bounds
{
public:
typedef T value_type;
typedef typename std::vector< Range<T> >::size_type size_type;
typedef typename std::vector< Range<T> > Ranges;
Bounds( T minx, T miny, T minz,
T maxx, T maxy, T maxz)
{
// fill Ranges vector
}
private:
Ranges ranges;
};
我需要提供什么来支持使用add_options接受Bounds
课程? ID
喜欢做类似的事情。可能的?
namespace po = boost::program_options;
po::options_description options("options");
options.add_options()
("extent,e", po::value< Bounds< double > >(), "Extent to clip points to")
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).
options(options).positional(p).run(), vm);
po::notify(vm);
if (vm.count("extent"))
{
Bounds<double> bounds = vm["extent"].as< Bounds<double> >();
// do other stuff
}
答案 0 :(得分:7)
诀窍是强制boost
将所有数字分类为位置值(不要与positional_options_description
混淆。你这样做的方法是定义一个style_parser
并将其交给command_line_parser
作为extra_style_parser
:
#include <boost/program_options/option.hpp>
#include <boost/lexical_cast/try_lexical_convert.hpp>
#include <boost/program_options/value_semantic.hpp>
using po = boost::program_options;
std::vector<po::option> ignore_numbers(std::vector<std::string>& args)
{
std::vector<po::option> result;
int pos = 0;
while(!args.empty()) {
const auto& arg = args[0];
double num;
if(boost::conversion::try_lexical_convert(arg, num)) {
result.push_back(po::option());
po::option& opt = result.back();
opt.position_key = pos++;
opt.value.push_back(arg);
opt.original_tokens.push_back(arg);
args.erase(args.begin());
} else {
break;
}
}
return result;
}
一旦你拥有它,这就是你如何使用它:
po::store(po::command_line_parser(argc, argv)
.extra_style_parser(&po::ignore_numbers)
.options(commands)
.run(), vm);
现在可以同时使用负数和短命令行参数。
但是,仍然存在问题,没有办法限制每个参数所采用的标记数,如果使用位置参数,这可能会有问题。例如,像这样的东西不起作用:
foo --coords 1 2 3 4 bar.baz
为了解决这个问题,我们需要添加一种强制参数所需的令牌数量的方法:
template<class T, class charT = char>
class bounded_typed_value : public po::typed_value<T, charT>
{
public:
bounded_typed_value(T* store_to)
: typed_value<T, charT>(store_to), m_min(-1), m_max(-1) {}
unsigned min_tokens() const {
if(m_min < 0) {
return po::typed_value<T, charT>::min_tokens();
} else {
return (unsigned)m_min;
}
}
unsigned max_tokens() const {
if(m_max < 0) {
return po::typed_value<T, charT>::max_tokens();
} else {
return (unsigned)m_max;
}
}
bounded_typed_value* min_tokens(unsigned min_tokens)
{
if(min_tokens > 1) {
po::typed_value<T, charT>::multitoken();
}
m_min = min_tokens;
return this;
}
bounded_typed_value* max_tokens(unsigned max_tokens)
{
if(max_tokens > 1) {
po::typed_value<T, charT>::multitoken();
}
m_max = max_tokens;
return this;
}
bounded_typed_value* fixed_tokens(unsigned num_tokens)
{
if(num_tokens > 1) {
po::typed_value<T, charT>::multitoken();
}
m_min = num_tokens;
m_max = num_tokens;
return this;
}
private:
int m_min;
int m_max;
};
template<class T, class charT = char>
bounded_typed_value<T, charT>*
bounded_value()
{
return new bounded_typed_value<T, charT>(0);
}
你现在可以像这样把它们放在一起:
po::positional_options_description p;
p.add("file-name", -1);
boost::program_options::options_description desc;
desc.add_options()
("coords,c", boost::program_options::bounded_value<vector<double>>()->fixed_tokens(4), "Bounding box");
po::store(po::command_line_parser(argc, argv)
.extra_style_parser(&po::ignore_numbers)
.positional(p)
.options(commands)
.run(), vm);
答案 1 :(得分:2)
处理指定here的负数的方法也可能适合您。
我正在通过简单的解析器解析它
store(command_line_parser(argc, argv).options(commands).run(), vm);
,但解决方案是使用扩展 之一:
parse_command_line
答案 2 :(得分:1)
简单的方法是将参数包装在引号中: mycommand --extent'-1.0 - 2.0 - 3.0 1.0 2.0 3.0' - some-other-argument somevalue