Infinity not constexpr

[亡魂溺海] 提交于 2019-12-04 17:51:21

问题


I wanted to test the behavior of floats near infinity. For that I naively wrote the following code:

#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;
}

The interesting part to me was that this compiles fine in GCC 7.2 but fails on Clang 5 (complaining about non-constexpr assign of foo).

AFAIK, since C++11, std::numeric_limits<float>::infinity() and infinity() are constexpr, so I am wondering where the problem lies for Clang.


EDIT 1:

Removed unnecessary static_assert. Thanks for pointing to division by 0. IMO the quoted standards text there does not apply here!?

And the obligatory godbolt link: https://godbolt.org/g/Nd5yF9

EDIT 2:

Note that the same behavior applies to:

constexpr float foo = std::numeric_limits<float>::infinity() - 100.0f;

回答1:


I'm not particularly familiar with floating point rules, but I'd suspect that we might be running afoul of [expr]/4:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

Which, in turn, means we run afoul of [expr.const]/2.6:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions: [...] an operation that would have undefined behavior as specified in [intro] through [cpp] of this document

That means the initializer for foo isn't a constant expression, so we can't initialize a constexpr object with it.


If infinity() - epsilon() is well-defined for float, this is a clang bug, the code is well-formed. If it's not well-defined for float, this is a gcc bug.



来源:https://stackoverflow.com/questions/46372614/infinity-not-constexpr

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!