【发布时间】:2019-09-29 13:32:02
【问题描述】:
我正在阅读Infinity not constexpr,这似乎表明创建无穷大是未定义的行为:
如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。
不过,如果std::numeric_limits::is_iec559 等于真,那似乎给了我们更多的保证。
下面的代码利用这个保证来创建一个无限数。在constexpr 上下文中执行时,会导致编译器失败,因为这是undefined behavior,以防is_iec559 等于false。
// clang++ -std=c++17 -O3
#include <limits>
constexpr double createInfinity()
{
static_assert(std::numeric_limits<double>::is_iec559, "asdf");
double d = 999999999999;
while (d != std::numeric_limits<double>::infinity())
{
d *= d;
}
return -1*d;
}
static_assert(createInfinity() == std::numeric_limits<double>::infinity(), "inf");
由于此函数总是导致无穷大,因此永远不能在有效的 C++ 程序中调用它。然而,正如我们在is_iec559 上断言的那样,我们得到了额外的保证。这个程序还无效吗?
- 如果无效?拥有
is_iec559有什么意义? - 如果有效?为什么它在运行时有效而不在 constexpr 上下文中有效?
(答案可以同时使用C++17作为即将推出的C++20,请明确指出使用哪个)
【问题讨论】:
-
“为什么它在运行时有效,而不是在 constexpr 上下文中?”谁说它不是?
-
“它似乎给了我们更多的保证”。有什么保证?
-
不幸的是,浮点在 C 和 C++ 标准中是一团糟。诸如“数学定义”和“可表示值的范围”之类的短语在 C++ 中从未定义过,尽管 C 说具有无穷大使得后者包含所有实数。但这并没有说明无穷大自身是否在范围内(例如,对于
inf+0),并且无论如何都不是C++的规范。 -
现在我们知道有两个浮点世界:IEC 559 世界和
asdf世界。
标签: c++ floating-point language-lawyer c++17 c++20