当尝试获取boost::optional对象的值时,BOOST_ASSERT用于确保该对象确实已初始化。
但是,当取消引用未初始化的可选对象时,我希望抛出一个异常--有什么方法可以在发布版本中实现这种行为吗?如果没有,有没有其他类似的库有这种行为?
我讨厌在每次取消引用对象之前都使用is_initialized方法,而且我也希望避免将可选类包装在我自己的类中以获得此行为。
发布于 2010-01-27 10:54:02
不幸的是,optional没有提供这样的选项。optional的全部意义在于能够通过使用重载的布尔运算符检查该值是否存在。
可选的是设计的,它允许不在函数中抛出异常,而是返回一个带有值的成功/失败。
也许你应该总是返回一个值,如果它失败了,在函数内部抛出?
发布于 2015-07-04 08:20:31
您可以定义boost::assertion_failed(...)
和BOOST_ENABLE_ASSERT_HANDLER
来从boost::optional
抛出异常。
代码:
#include<boost/exception/to_string.hpp>
namespace boost{
void assertion_failed(char const* expr, char const* function, char const* file, long line){
throw std::runtime_error(std::string()
+ expr +
" from " + function +
" at " + file + ":" + boost::to_string(line)
);
}
}
#define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/optional.hpp>
#undef BOOST_ENABLE_ASSERT_HANDLER
int main(){
double d = *boost::optional<double>{}; // throws! (width fairly useful msg)
(void)d;
}
错误消息(如果未捕获异常)将如下所示:
terminate called after throwing an instance of 'std::runtime_error'
what(): this->is_initialized() from reference_type boost::optional<double>::get() [T = double] at /usr/include/boost/optional/optional.hpp:992
备注:
1)它可能需要assertion_failed
的细粒度定义才能在一般情况下有用。如果你想抛出一种不同的异常,除了在assertion_failed
函数中有一个条件之外,我不知道还有其他方法(对我来说,这也太老套了):
namespace boost{
void assertion_failed(char const* expr, char const* function, char const* file, long line){
if(std::string("this->is_initialized()") == expr) throw std::domain_error("optional is not intialized");
throw std::runtime_error(std::string()
+ expr +
" from " + function +
" at " + file + ":" + boost::to_string(line)
);
}
}
2)我不同意另一个答案,我认为一个人应该能够选择行为。而坚持使用assert
并不是一个好的选择。在我看来,在不涉及函数返回的上下文中使用boost::optional
。
3)现在有了std::experimental::optional
版本。奇怪的是,当使用*
(由于返回未检查的值,这与原始指针的非行为一致)取值时,他们决定对这个问题持不可知态度,但 .value()
成员可能会抛出std::experimental::bad_optional_access
异常。这是一个有趣的设计选择(再加上两种方式assert
都不是!我认为这是正确的事情。)
https://stackoverflow.com/questions/2146106
复制相似问题