gpt4 book ai didi

c++ - 使用 boost::program_options 接受负 double

转载 作者:IT老高 更新时间:2023-10-28 23:01:04 24 4
gpt4 key购买 nike

我需要能够拥有 boost::program_options解析一个 double 组在命令行上传递。对于正 double ,这没问题,当然(在 add_options 中使用带有 std::vector<double> 的多 token ),但是对于否定的,我知道这些都是模棱两可的论点。

以下是我想要学习的演示:

mycommand --extent -1.0 -2.0 -3.0 1.0 2.0 3.0 --some-other-argument somevalue

extent is to be backed by a Bounds class with at least one constructor that takes in six individual T arguments (in this case -- 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;
};

我还必须提供什么来支持使用 Bounds 中的 add_options类(class)? 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
}

最佳答案

诀窍是强制 boost 将所有数字分类为位置值(不要与 positional_options_description 混淆。这样做的方式是定义 style_parser 并将其作为 extra_style_parser 提供给 command_line_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

为了解决这个问题,我们需要添加一种方法来强制参数所需的 token 数量:

    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<std::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);

关于c++ - 使用 boost::program_options 接受负 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4107087/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com