使用Boost program_options指定级别(例如——verbose)
Specifying levels (e.g. --verbose) using Boost program_options
我的一些选项有多个级别,例如"冗长"。我希望我的用户在以下两种等效样式之间进行选择:
// 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
用Boost program_options库做这件事最简单的方法是什么?
这就是我设想的使用代码的方式。
- 我们使用
level_value
代替正常的program_options::value
- 通过
option_level<CHAR>(your_value)
,其中CHAR
是短选项字母,your_value
是可选级别,例如,提供
#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;
}
行为# 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
实施
#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;
}
# 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
我们需要一些东西来保持水平:
//________________________________________________________________________________________
// 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);}
增加或设置值的逻辑位于验证器中:
#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.");
}
}
这提供了program_options::value_semantic
覆盖,允许零或一个参数:
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);
}
相关文章:
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 将数字转换为字母(例如:123 转换为一二三)
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- 如何计算数据类型的范围,例如int
- 这是否符合C++标准:双响双响,例如!!(-0.0).
- 如何将CMSampleBufferRef/CIImage/UIImage转换为像素,例如uint8_t[]
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 如何使用文件中的文本,例如变量
- 输入值后,如何在一个括号下显示值,例如"{6,7,8,9}
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 初学者问题:如何使用这些晦涩难懂的命令,例如C++中的'RenderWindow'
- C++:将值 int(例如:0x00AAFAD8)转换为指针(指针本身也是 0x00AAFAD8 值)
- 具有多种约束(例如重量、体积等)的背包
- 较高值 n 的分割错误(例如 n=999997)
- 我正在尝试制作一个程序,在添加 n 天(整数)后告诉一个人什么是一天(例如星期一等)
- 在标准中,模板参数的语法在哪里定义,例如,'std::function<int(char)>'?
- 从/到 UTF-8/UTF-16 的转换需要(例如:utf8 -> 代码点,然后代码点到 utf16)或(例如:utf8 -> utf16)?
- 计算车辆之间的距离并设置速度,使距离保持不变,例如 5 米
- 使用Boost program_options指定级别(例如——verbose)