当试图获取boost :: optional对象的值时,BOOST_ASSERT用于确保对象确实已初始化。如何确保boost :: optional <T>对象在发布版本中初始化?
但是,我想在解除引用未初始化的可选项时引发异常 - 是否有任何方法在发布版本中获取此行为?如果没有,有没有其他类似的图书馆有这种行为?
我讨厌每次在解引用对象之前使用is_initialized方法,并且我还想避免在我自己的类中包装可选类以获得此行为。
当试图获取boost :: optional对象的值时,BOOST_ASSERT用于确保对象确实已初始化。如何确保boost :: optional <T>对象在发布版本中初始化?
但是,我想在解除引用未初始化的可选项时引发异常 - 是否有任何方法在发布版本中获取此行为?如果没有,有没有其他类似的图书馆有这种行为?
我讨厌每次在解引用对象之前使用is_initialized方法,并且我还想避免在我自己的类中包装可选类以获得此行为。
不幸的是,可选项不提供这样的选项。可选的要点是能够通过使用重载的bool操作符来检查值是否存在。
可选为设计,允许在功能不要将抛出异常,但与返回值成功/失败来代替。
也许你应该总是返回一个值,而如果失败的话会抛出函数吗?
这样做可能会违反允许可选返回值的目的,这正是我正在寻找的目标......如示例中所示: http://www.boost.org/doc/libs/1_41_0/libs/可选/ doc/html/boost_optional/examples.html#boost_optional.examples.optional_return_values – Danra 2010-01-27 10:59:20
@Danra - 如果值不存在,您明确指出您希望有异常 - 因此为什么不将它放在函数中,哪里更多合乎逻辑地去做,而不是等待它被解除引用? – 2010-01-27 11:15:47
它适用于很好地返回可选值。你问它是否返回了一个值,然后采取相应的行动。例外不应该是正常程序流程的工具。 – 2010-01-27 11:16:40
您可以定义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
这两种方式都没有,我认为这是正确的选择)。
这是我从boost :: optional中错过的东西。有一个get_or_throw(例外)和get_or_else(另一个)会很好。我更愿意包装它,它能很好地传达我的想法。 – daramarak 2011-12-06 13:58:46
@daramarak这里有一个'safe_get'代码:http://boost.2283326.n4.nabble。com/optional-how-to-make-boost-optional-throw-if-trying-to-access-uninitialized-value-tp2591333p2591334.html。另请参阅我的答案。 – alfC 2015-07-04 08:21:32