In C++17, are you allowed to modify global variables in a constexpr
function?
#include <iostream>
int global = 0;
constexpr int Foo(bool arg) {
if (arg) {
return 1;
}
return global++;
}
int main() {
std::cout << global;
Foo(true);
std::cout << global;
Foo(false);
std::cout << global;
}
I wouldn't expect you to be able to, but clang 6 allows it: https://godbolt.org/g/UB8iK2
GCC, however, doesn't: https://godbolt.org/g/ykAJMA
Which compiler is correct?
Which compiler is correct?
Clang is right.
The definition of a constexpr
function as per dcl.constexpr/3
The definition of a
constexpr
function shall satisfy the following requirements:
(3.1) its return type shall be a literal type;
(3.2) each of its parameter types shall be a literal type;
(3.3) its function-body shall be= delete
,= default
, or a compound-statement that does not contain:
(3.3.1) an asm-definition,
(3.3.2) a goto statement,
(3.3.3) an identifier label,
(3.3.4) a try-block, or
(3.3.5) a definition of a variable of non-literal type or of static or thread storage duration or for which no initialization is performed.
Also as per dcl.constexpr/5:
For a
constexpr
function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, a constant initializer for some object ([basic.start.static]), the program is ill-formed, no diagnostic required.
Foo(true)
could be evaluated to a core constant expression (i.e 1
).
Also, Foo(false)
could be but is not required to be constant evaluated.
CONCLUSION
Thus, a bug in GCC.