如何在 Boost 程序选项中获得更好的错误消息
在下面的代码中,我使用程序选项从命令行或文件读取参数。另外,可以在运行时通过 ConfigProxy::setConfig 以编程方式设置选项
po::options_description desc("Allowed options");
desc.add_options()
...
("compression", po::value<int>(), "set compression level");
po::variables_map vm;
class ConfigProxy
{
template< typename T>
void setConfig( const std::string key, const T value ){
... // check if the key exists in variable map "vm"
// key exists, set the value
runtimeConfig[key] = po::variable_value( boost::any(value), false);
}
po::variable_value& operator[] (const std::string key) const{
...
// if exists in runtimeConfig return the value in runtimeConfig
// of type program_options::variable_value
...
// else return value in variable map "vm"
}
std::map<std::string, boost::program_options::variable_value> runtimeConfig;
}
,通过 ConfigProxy 检索选项值
if( vm.count("compression") ){
int value = proxyConfig["compression"].as<int>();
...
}
但是,如果用户提供的“压缩”选项值的类型错误,例如
configProxy.setConfig("compression", "12" );
...
int value = configProxy["compression"].as<int>(); // was set as string
然后抛出异常
what(): boost::bad_any_cast: failed conversion using boost::any_cast
该异常清楚地表明了类型转换问题。但该消息对于用户找出哪个选项负责错误似乎没有多大帮助。
有没有更好的方法来通知用户此类错误,而不是抛出 bad_any_cast 异常?
----- 编辑 --------------------------
感谢 Luc Danton 和 Tony,我找到了程序选项如何显示错误。
void validate(boost::any& v,
const std::vector< std::basic_string<charT> >& xs,
T*, long)
{
validators::check_first_occurrence(v);
std::basic_string<charT> s(validators::get_single_string(xs));
try {
v = any(lexical_cast<T>(s));
}
catch(const bad_lexical_cast&) {
boost::throw_exception(invalid_option_value(s));
}
}
我认为,通过实现逻辑,我可以摆脱 bad_any_cast 异常。
In the code below, I used program options to read parameters from command-line or file. In addition, options can be set programatically at runtime through ConfigProxy::setConfig
po::options_description desc("Allowed options");
desc.add_options()
...
("compression", po::value<int>(), "set compression level");
po::variables_map vm;
class ConfigProxy
{
template< typename T>
void setConfig( const std::string key, const T value ){
... // check if the key exists in variable map "vm"
// key exists, set the value
runtimeConfig[key] = po::variable_value( boost::any(value), false);
}
po::variable_value& operator[] (const std::string key) const{
...
// if exists in runtimeConfig return the value in runtimeConfig
// of type program_options::variable_value
...
// else return value in variable map "vm"
}
std::map<std::string, boost::program_options::variable_value> runtimeConfig;
}
through ConfigProxy, the option value is retrieved
if( vm.count("compression") ){
int value = proxyConfig["compression"].as<int>();
...
}
However, if the "compression" option value provided by the user is in wrong type, for example
configProxy.setConfig("compression", "12" );
...
int value = configProxy["compression"].as<int>(); // was set as string
then exception is thrown
what(): boost::bad_any_cast: failed conversion using boost::any_cast
The exception clearly shows the type cast problem. But the message seems not so helpful to users for finding out which option is responsible for the error.
Is there a better way to inform users about this type of error, instead of throwing bad_any_cast exception?
----- Edit --------------------------
Thanks to Luc Danton and Tony, I have found how Program options shows the errors.
void validate(boost::any& v,
const std::vector< std::basic_string<charT> >& xs,
T*, long)
{
validators::check_first_occurrence(v);
std::basic_string<charT> s(validators::get_single_string(xs));
try {
v = any(lexical_cast<T>(s));
}
catch(const bad_lexical_cast&) {
boost::throw_exception(invalid_option_value(s));
}
}
I think, by implementing the logic, I can get rid of the bad_any_cast exception.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你尝试过吗?
注意
po::value()
。您在此处指定关联值的类型为int
。当用户传递 Boost.ProgramOptions 无法转换为int
的内容时,程序会失败并显示错误消息:这毕竟是库的角色之一。
您必须执行
vm["compression"].as()
的原因是因为指定了压缩
的类型在函数调用中(括号中的三元组),运行时世界中的某些东西。这不会影响vm["compression"]
的返回类型,因此它需要是某种动态类型模拟。因此,当您查询未指定的类型时,会出现boost::any_cast_failed
异常。Have you tried it?
Notice
po::value<int>()
. You specify here that the associated value has typeint
. When the user passes something that Boost.ProgramOptions can't convert toint
, the program fails with an error message:That's one of the roles of the library after all.
The reason you do have to do
vm["compression"].as<int>()
is because the the type ofcompression
is specified in a function call (the triplet in parentheses), something in the runtime world. This can't influence the return type ofvm["compression"]
, so it needs to be some dynamic type emulation. Hence theboost::any_cast_failed
exception when you query a type that you did not specify.你能不能把这个:
放在一个
try catch
块中,在其中捕获 boost 抛出的bad_any_cast
异常,然后通过以下任一方式向你自己的用户显示一条消息抛出(重排)您创建的类型的新异常或通过向 std::cout 写入消息,我想很大程度上取决于您的应用程序。所以:
Can you not put this:
in a
try catch
block where you catch thebad_any_cast
exception thrown by boost is caught and then show a message to the user of your own, by either throwing (retrow) a new exception of a type you have created or by writing a message to thestd::cout
, I guess much depending on your application.so: