无限不是constexpr

abe*_*ier 11 c++ c++17

我想测试无限远附近浮子的行为.为此我天真地写了下面的代码:

#include <limits>
#include <iostream>

int main() {
    constexpr float foo = std::numeric_limits<float>::infinity() - std::numeric_limits<float>::epsilon();
    std::cout << foo << std::endl;
    return foo;
}
Run Code Online (Sandbox Code Playgroud)

对我来说有趣的部分是,这在GCC 7.2中编译得很好但在Clang 5上失败(抱怨非constexpr赋值foo).

据我所知,因为C++ 11,std::numeric_limits<float>::infinity()并且infinity()都是constexpr,所以我不知道问题出在哪里了锵.


编辑1:

删除不必要的static_assert.感谢您指出除以0. IMO引用的标准文本在这里不适用!?

强制性的Godbolt链接:https://godbolt.org/g/Nd5yF9

编辑2:

请注意,相同的行为适用于:

constexpr float foo = std::numeric_limits<float>::infinity() - 100.0f;
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 8

我对浮点规则并不是特别熟悉,但我怀疑我们可能会遇到[expr]/4:

如果在评估表达式期间,结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义.

反过来,这意味着我们与[expr.const] /2.6发生冲突:

表达式e是核心常量表达式,除非根据抽象机器的规则评估e将评估以下表达式之一:[...]具有未定义行为的操作,如[intro]中所指定[] cpp]这个文件

这意味着初始化foo器不是常量表达式,因此我们无法constexpr用它初始化对象.


如果infinity() - epsilon()定义明确float,这是一个铿锵的错误,代码是格式良好的.如果它没有明确定义float,这是一个gcc错误.

  • 或者它可以为一个而不是另一个定义:D [Clang的constexpr评估者](https://github.com/llvm-mirror/clang/blob/362362f51fcee8fdc49e0a2ad15ad7b43c4f7fa76/lib/AST/ExprConstant.cpp#L2137)是肯定将所有无限或NaN产生的表达式视为UB.C++标准对浮点几乎没有什么可说的. (11认同)