在C++中使用NaNs的最佳方式是什么?
我找到std::numeric_limits<double>::quiet_NaN()和std::numeric_limits<double>::signaling_NaN()了。我想使用signaling_NaN来表示一个未初始化的变量,如下所示:
double diameter = std::numeric_limits<double>::signaling_NaN();然而,这会在赋值时发出信号(引发异常)。我希望它在使用时引发异常,而不是在赋值时。
有没有办法在不引发赋值异常的情况下使用signaling_NaN?有没有一个很好的、可移植的signaling_NaN替代方案,可以在使用时引发浮点异常?
发布于 2008-11-11 18:32:36
经过更多的研究,signaling_NaN看起来就像所提供的那样没有用。如果启用了浮点异常,则调用它将被视为处理信号NaN,因此它会立即引发异常。如果禁用了浮点异常,则处理信令NaN会自动将其降级为静默NaN,因此signaling_NaN在这两种方式中都不起作用。
Menkboy's code可以工作,但尝试使用信令NaNs会遇到其他问题:没有可移植的方法来启用或禁用浮点异常(如here和here所暗示的),如果您依赖于启用异常,则第三方代码可能会禁用它们(如here所述)。
所以看起来Motti's solution确实是最好的选择。
发布于 2008-10-25 20:02:28
发信号NAN的意思是,当CPU遇到NAN时,就会触发一个信号(由此得名)。如果您想要检测未初始化的变量,那么提高编译器上的警告级别通常会检测到所有使用未初始化的值的路径。如果不是这样,您可以使用一个包装类来存储一个布尔值,该布尔值表示该值是否已初始化:
template <class T>
class initialized {
T t;
bool is_initialized;
public:
initialized() : t(T()), is_initialized(false) { }
initialized(const T& tt) : t(tt), is_initialized(true) { }
T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }
operator T&() {
if (!is_initialized)
throw std::exception("uninitialized");
return t;
}
};发布于 2008-10-24 22:36:00
您可以将信令NaN写入变量,而不会触发异常,如下所示(nb:未测试)
void set_snan( double &d )
{
long long *bits = (long long *)&d;
*bits = 0x7ff0000080000001LL;
}它可以在大多数地方使用,但不是100%便携的。
https://stackoverflow.com/questions/235386
复制相似问题