我正在读无穷大不是 constexpr,这似乎表明创建无穷大是未定义的行为:
[expr]/4:
如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。
然而,如果std::numeric_limits::is_iec559equal true,似乎给了我们更多的保证。
下面的代码利用此保证来创建无限数量。当执行时constexpr
上下文,它会导致编译器失败,因为这是undefined behavior
以防万一is_iec559
等于假。
// 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,请明确指出使用哪一个)
等待一段时间有时会有所帮助,看起来 Clang 已经收到了一个补丁,可以使此代码编译:https://reviews.llvm.org/D63793
在r329065之前,我们使用[-max, max]作为可表示的范围
值,因为 LLVM 的 fptrunc 不保证定义的行为
从较大的浮点类型截断为较小的浮点类型。现在
已修复,我们可以让 clang 遵循正常的 IEEE 754 语义
取较大范围[-inf,+inf]作为可表示的范围
价值观。
值得注意的一个有趣的元素(该修订版中的部分代码注释)是,导致 NaN 的操作(尚)是不允许的:
// [expr.pre]p4:
// If during the evaluation of an expression, the result is not
// mathematically defined [...], the behavior is undefined.
// FIXME: C++ rules require us to not conform to IEEE 754 here.
编译器资源管理器中的示例:
#include <limits>
constexpr double createNan()
{
static_assert(std::numeric_limits<double>::is_iec559, "asdf");
double d = std::numeric_limits<double>::infinity() / std::numeric_limits<double>::infinity();
return -1*d;
}
static_assert(createNan() != 0., "NaN");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)