Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Infinity not constexpr

Tags:

c++

c++17

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;
like image 378
abergmeier Avatar asked Sep 22 '17 20:09

abergmeier


1 Answers

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.

like image 98
Barry Avatar answered Oct 11 '22 08:10

Barry