Im having trouble with the following code, I am trying to write a compile time square root function. The code compiles on the most recent clang 6.0. yet fails on the most recent version of gcc 8.0. the issue seems to be with the initialisation of the struct.
GCC output
error: uninitialized variable 'sqrtNewtonRaphson' in 'constexpr' context
} sqrtNewtonRaphson;
^~~~~~~~~~~~~~~~~
The last version of gcc that this code compiles on is gcc 6.3, in the following versions after that, compile_time_sqrt_ver1(double) fails to compile.
//------------------------------------------------------------
constexpr double
compile_time_sqrt_ver1(double x) {
struct {
constexpr double operator() (double x, double current, double previous) {
return current == previous ? current : (*this)(x, 0.5 * (current + x / current), current);
}
} sqrtNewtonRaphson;
return x >= 0 && x < std::numeric_limits<double>::infinity()
? sqrtNewtonRaphson(x, x, 0)
: std::numeric_limits<double>::quiet_NaN();
}
//------------------------------------------------------------
int main() {
constexpr double test_v1 = compile_time_sqrt_ver1(24);
return test_v1;
}
The solution I found to this is to add {} at the end of the struct making it compile in the most recent version of gcc as well as clang. why is this?
//------------------------------------------------------------
constexpr double
compile_time_sqrt_ver2(double x) {
struct {
constexpr double operator() (double x, double current, double previous) {
return current == previous ? current : (*this)(x, 0.5 * (current + x / current), current);
}
} sqrtNewtonRaphson{}; // <- change {}
return x >= 0 && x < std::numeric_limits<double>::infinity()
? sqrtNewtonRaphson(x, x, 0)
: std::numeric_limits<double>::quiet_NaN();
}
//------------------------------------------------------------
int main() {
constexpr double test_v2 = compile_time_sqrt_ver2(24);
return test_v2;
}