Given that the C standard library doesn't provide constexpr versions of the cmath functions, consider the program below.
#include <cmath>
#include <cstring>
int main()
{
constexpr auto a = std::pow(2, 10);
constexpr auto b = std::strlen("ABC");
}
As expected, MSVC and clang fail to compile this, because constexpr
variables are initialized from functions that are not declared constexpr
.
g , however, compiles this. The version of g doesn't seem to matter.
(See them all in compiler explorer)
How does g achieve this? Is this correct (allowed) compiler behavior?
CodePudding user response:
The resolution of LWG 2013 was that implementations are not allowed to declare non-constexpr
functions as constexpr
, so gcc is non-conformant by allowing these to be evaluated at compile time.
That said, GCC does not actually mark the needed functions as constexpr
. What it instead does is replace those calls very early on with __builtin_pow
and __builtin_strlen
, which it can compute at compile time (the std::
versions call the libc versions, which can't). This is a compiler extension.
If you compile with -fno-builtin
, it also fails to compile both std::pow
and std::strlen
, but you can make both clang and GCC compile this by explicitly writing out __builtin_pow(2, 10)
and __builtin_strlen("ABC")
.
CodePudding user response:
As noted, the C standard library doesn't currently support constexpr
evaluation of cmath functions. However, that doesn't prevent individual implementations from having non-standard code. GCC has a nonconforming extension that allows constexpr
evaluation.