With GCC 9.1, when calling std::numeric_limits's functions with floating-point types, they return 0 in most cases.
This happens in a project I'm working on, and there is no issue with MSVC, GCC 8.3 or Clang 8.0. <double>::epsilon()
sometimes has a correct value, but when called from other files it may evaluate to 0 as well.
// Commented values at the end of the lines are the values given by the debugger
// Making the variable constexpr doesn't change their values
auto intMax = std::numeric_limits<int>::max(); // {int} 2147483647
auto floatMax = std::numeric_limits<float>::max(); // {float} 0
auto floatEpsilon = std::numeric_limits<float>::epsilon(); // {float} 0
auto floatMin = std::numeric_limits<float>::min(); // {float} 0
auto floatLowest = std::numeric_limits<float>::lowest(); // {float} -0
auto doubleMax = std::numeric_limits<double>::max(); // {double} 0
auto doubleEpsilon = std::numeric_limits<double>::epsilon(); // {double} 2.2204460492503131e-16
auto doubleMin = std::numeric_limits<double>::min(); // {double} 0
auto doubleLowest = std::numeric_limits<double>::lowest(); // {double} -0
std::cout << std::setprecision(10) << std::fixed
<< "Max int = " << std::numeric_limits<int>::max()
<< "\n"
<< "\nMax float = " << std::numeric_limits<float>::max()
<< "\nEpsilon float = " << std::numeric_limits<float>::epsilon()
<< "\nMin float = " << std::numeric_limits<float>::min()
<< "\nLowest float = " << std::numeric_limits<float>::lowest()
<< "\n"
<< "\nMax double = " << std::numeric_limits<double>::max()
<< "\nEpsilon double = " << std::numeric_limits<double>::epsilon()
<< "\nMin double = " << std::numeric_limits<double>::min()
<< "\nLowest double = " << std::numeric_limits<double>::lowest() << std::endl;
(The <int>::max()
is left as a reference here)
Result in an independent file (correct values):
Max int = 2147483647
Max float = 3.40282e+38
Epsilon float = 1.19209e-07
Min float = 1.17549e-38
Lowest float = -3.40282e+38
Max double = 1.79769e+308
Epsilon double = 2.22045e-16
Min double = 2.22507e-308
Lowest double = -1.79769e+308
Result in the project:
Max int = 2147483647
Max float = 0
Epsilon float = 0
Min float = 0
Lowest float = -0
Max double = 0
Epsilon double = 2.22045e-16
Min double = 0
Lowest double = -0
When compiling a dedicated file indepentenly, the values are correct: the issue is then not from GCC (as I expected anyway), but most likely from the project's configuration.
EDIT: compiling a project's file (on which this issue occurs at the moment) independently gives correct results as well. With gcc -dM -E
, the __DBL_MAX__
is defined to double(1.79769313486231570814527423731704357e+308L)
.
The __DBL_MAX__
value is defined, code surrounded by an ifdef is executed:
#ifdef __DBL_MAX__
#pragma message "__DBL_MAX__ defined"
#endif
/*
note: #pragma message: __DBL_MAX__ defined
40 | #pragma message "__DBL_MAX__ defined"
| ^~~~~~~~~~~~~~~~~~~~~
*/
GDB gives the same exact value, so no problem on the output part. Outputting XXX_YYY
or __XXX_YYY__
gives the same results, since numeric_limits' functions call them anyway.
To be 100% clear: std::numeric_limits<double>::max() == 0
returns true, so there is no problem on the output part. It is just left here as a reference.
What could be the reason(s) GCC produces such behavior? Aren't __XXX_YYY__
built-in values anyway? How can they possibly hold 0?
So the error came from (at least indirectly) the precompiled headers, which we use with cotire for CMake.
Every file included by those headers, manually included individually in the "problematic" files, did not reproduce the issue.
Although a bit weird, I don't see any viable explanation other than cotire for now. It has apparently already been reported to have problems with limits, as per this thread: C++ Cmake build with cotire and gtest - error with float.h
The temporary solution will then be to disable precompiled headers with GCC 9.1+. If anyone has had the same kind of issue, feel free to add comments or answers if you do know why and how this happens.
Thanks to Giovanni, Kamil and n.m in the comments who led me in the right direction!