指定级别使用Boost program_options(例如--verbose) [英] Specifying levels (e.g. --verbose) using Boost program_options
本文介绍了指定级别使用Boost program_options(例如--verbose)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我的一些选项有多个层次,例如的冗长。
我想我的用户提供了以下两个等价的风格之间进行选择:
//没有参数:1冗长
my_program -v//算'V的:4冗长
my_program -vv --something_else XYZ -vv//指定的值:4冗长
my_program --verbose 3
什么是使用Boost库program_options这样做的最简单的方法?
解决方案
这是怎么设想正在使用的code。
- 我们使用
LEVEL_VALUE级
代替正常的program_options的价值::
- 通过
option_level< CHAR>(your_value)
,其中CHAR
是短选项字母,而your_value
是可选的水平,例如,冗长,供给
示例
的#include<升压/ program_options.hpp>
使用名字空间boost;
使用空间boost :: program_options;诠释的main()
{
无符号的冗长= 0U;
无符号something_else = 0U; options_description递减(「购股权」);
desc.add_options()
(详细,V,
LEVEL_VALUE级(option_level<'V'>(安培;冗长))
在每一个额外的冗余级别打印更详细的消息。)
(something_else,的,
值<无符号>(安培; something_else); 返回0;
}
行为
#冗长= 7
test_options -vvvvv --something_else 5 -vv3#覆盖冗长决赛
test_options -vvvvv --something_else 5 -v 7 -v 3#没有参数总是递增:冗长= 6
test_options -v --verbose 3 -v 5
实施
我们需要一些东西来支持水平:
<$p$p><$c$c>//________________________________________________________________________________________// t_option_level// ________________________________________________________________________________________结构t_option_level {
上市:
无符号N;
明确t_option_level(无符号N_ = 0):N(_){}
t_option_level&安培; INC {N + =由(由= 1无符号);返回*此;}
t_option_level&安培;集(无符号VAL){N = VAL;返回*此;}
};模板&LT; typename的U&GT;
内嵌t_option_level * option_level(U * U)
{返回reinter pret_cast&LT; t_option_level *&GT;(U);}
递增或验证设置的值生命的逻辑:
的#include&LT;升压/ program_options.hpp&GT;
#包括LT&;升压/ program_options / options_description.hpp&GT;
// ________________________________________________________________________________________
//
//验证
// ________________________________________________________________________________________
模板&LT;无符号SHORT_NAME&GT;
void验证(升压::任何和放大器; V,
常量的std ::矢量&lt;标准::字符串&GT;&安培;值,
t_option_level&LT;&SHORT_NAME GT; * / * * TARGET_TYPE /,INT)
{
使用空间boost :: program_options; //
//获取当前值
//
t_option_level&LT;&SHORT_NAME GT;一世;
如果(!v.empty())
I =提振:: any_cast&LT; t_option_level&LT;&SHORT_NAME GT;&GT;(五); //
//提取任何参数
//
常量标准::字符串&安培; S =验证:: get_single_string(值true);
如果(s.empty())
{
V =的boost ::任何(i.inc());
返回;
} 焦炭SHORT_NAME = SHORT_NAME;
//多个值的
如果(S ==标准::字符串(s.length(),SHORT_NAME))
{
V =的boost ::任何(i.inc(s.length()+ 1));
返回;
} //匹配号码
提高::正则表达式R(^(\\\\ D +)$); //做正则表达式匹配和有趣的部分转换为
// int类型。
提高:: SMATCH什么;
如果(regex_match(S,什么,R))
{
V =的boost ::任何(i.set(升压:: lexical_cast的&LT;无符号&GT;(S)));
返回;
}
其他
{
扔VALIDATION_ERROR(VALIDATION_ERROR :: invalid_option_value,\\+ S +\\不是一个有效的论据。);
}}
这提供了 program_options :: value_semantic
覆盖允许零个或一个参数:
模板&LT; T类,类图=字符&GT;
类t_level_value:公众的boost :: program_options :: typed_value&LT; T,图表&GT;
{
上市:
/ **构造函数。在'store_to'参数告诉在哪里存储
当它被称为价值。该参数可以为NULL。 * /
t_level_value(T * store_to)
:升压:: program_options :: typed_value&LT; T,图表&GT;(store_to)
{}
无符号min_tokens()const的
{
返回0;
} 无符号max_tokens()const的
{
返回1;
}
};模板&LT;类T&GT;
t_level_value&LT; T&GT; *
LEVEL_VALUE级(T * V)
{
返回新t_level_value&LT; T&GT;(五);
}
Some of my options have multiple levels, e.g. of "verbosity". I would like my users to choose between the following two equivalent styles:
// no argument: verbosity of 1
my_program -v
// count the 'v's: verbosity of 4
my_program -vv --something_else XYZ -vv
// specify the value: verbosity of 4
my_program --verbose 3
What is the easiest way of doing this with the Boost program_options library?
解决方案
This is how I envisage the code being used.
- We use
level_value
in place of the normalprogram_options::value
- pass
option_level<CHAR>(your_value)
whereCHAR
is the short option letter, andyour_value
is the optional level, e.g. verbosity, being supplied
Example
#include <boost/program_options.hpp>
using namespace boost;
using namespace boost::program_options;
int main()
{
unsigned verbosity = 0U;
unsigned something_else = 0U;
options_description desc("options");
desc.add_options()
("verbose,v",
level_value(option_level<'v'>(&verbosity)),
"Print more verbose messages at each additional verbosity level.")
("something_else,s",
value<unsigned>(&something_else);
return 0;
}
Behavior
# verbosity = 7
test_options -vvvvv --something_else 5 -vv
# final verbosity of 3 overrides
test_options -vvvvv --something_else 5 -v 7 -v 3
# no argument always increments: verbosity = 6
test_options -v 3 --verbose 5 -v
Implementation
We need something to hold the level:
//________________________________________________________________________________________
// t_option_level
//________________________________________________________________________________________
struct t_option_level {
public:
unsigned n;
explicit t_option_level(unsigned n_ = 0):n(n_){}
t_option_level& inc(unsigned by = 1){n += by; return *this;}
t_option_level& set(unsigned val){n = val; return *this;}
};
template <typename U>
inline t_option_level* option_level(U* u)
{return reinterpret_cast<t_option_level*>(u);}
The logic to increment or set the value lives in the validator:
#include <boost/program_options.hpp>
#include <boost/program_options/options_description.hpp>
//________________________________________________________________________________________
//
// validate
//________________________________________________________________________________________
template <unsigned SHORT_NAME>
void validate(boost::any& v,
const std::vector<std::string>& values,
t_option_level<SHORT_NAME>* /*target_type*/, int)
{
using namespace boost::program_options;
//
// Get the current value
//
t_option_level<SHORT_NAME> i;
if (!v.empty())
i = boost::any_cast<t_option_level<SHORT_NAME>>(v);
//
// Extract any arguments
//
const std::string& s = validators::get_single_string(values, true);
if (s.empty())
{
v = boost::any(i.inc());
return;
}
char short_name = SHORT_NAME;
// multiple 'values's
if (s == std::string(s.length(), short_name))
{
v = boost::any(i.inc(s.length() + 1));
return;
}
// match number
boost::regex r("^(\\d+)$");
// Do regex match and convert the interesting part to
// int.
boost::smatch what;
if (regex_match(s, what, r))
{
v = boost::any(i.set(boost::lexical_cast<unsigned>(s)));
return;
}
else
{
throw validation_error(validation_error::invalid_option_value, "\"" + s + "\" is not a valid argument.");
}
}
This provides the program_options::value_semantic
override to allow zero or one arguments:
template<class T, class charT = char>
class t_level_value : public boost::program_options::typed_value<T, charT>
{
public:
/** Ctor. The 'store_to' parameter tells where to store
the value when it's known. The parameter can be NULL. */
t_level_value(T* store_to)
: boost::program_options::typed_value<T, charT>(store_to)
{}
unsigned min_tokens() const
{
return 0;
}
unsigned max_tokens() const
{
return 1;
}
};
template<class T>
t_level_value<T>*
level_value(T* v)
{
return new t_level_value<T>(v);
}
这篇关于指定级别使用Boost program_options(例如--verbose)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文