在下面的代码中,我使用程序选项从命令行或文件中读取参数。此外,可以通过 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异常。
答案 0 :(得分:4)
你试过吗?
("compression", po::value<int>(), "set compression level");
注意po::value<int>()
。您在此处指定关联值的类型为int
。当用户传递Boost.ProgramOptions无法转换为int
的内容时,程序将失败并显示错误消息:
error: in option 'compression': invalid option value
毕竟,这是图书馆的一个角色。
你做必须做vm["compression"].as<int>()
的原因是因为compression
的类型是在函数调用中指定的(括号中的三元组),运行时中的某些内容世界。这不会影响vm["compression"]
的返回类型,因此需要进行一些动态类型仿真。因此,当您查询未指定的类型时会出现boost::any_cast_failed
异常。
答案 1 :(得分:2)
你能不能说出来:
if( vm.count("compression") ){
int value = vm["compression"].as<int>();
...
}
在try catch
块中,捕获由boost引发的bad_any_cast
异常,然后通过抛出(转发)类型的新异常来向您自己的用户显示消息您已创建或通过向std::cout
发送消息,我想这取决于您的应用程序。
这样:
try {
if( vm.count("compression") ){
int value = vm["compression"].as<int>();
...
}
}
catch(const boost::bad_any_cast& ex)
{
//rethrow exception of your own to show to the user or print msg to std::cout
}