I am using g++4.8.0, which doesn't contain earlier constexpr
bug. Thus below code works fine:
constexpr int size() { return 5; }
int array[size()];
int main () {}
However, if I enclose both the variable inside a class
as static
, then it gives compiler error:
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
int main () {}
Here is the error:
error: size of array ‘array’ is not an integral constant-expression
Is it forbidden to use constexpr
in such a way or yet another g++ bug?
Yes, it is ill-formed. Here's why:
A
constexpr
function needs to be defined (not just declared) before being used in a constant expression.So for example:
function definitions inside a class specifier (as well as initializers and default parameters) are essentially parsed in an order like they were defined outside the class.
So this:
Is parsed in this order:
That is, parsing of function bodies are defered until after the class specifier.
The purpose of this deferral of function body parsing is so that function bodies can forward reference class members not yet declared at that point, and also so they can use their own class as a complete type:
Compared to at namespace scope:
At
POINT A
, the compiler doesn't have the definition ofsize()
yet, so it can't call it. For compile-time performanceconstexpr
functions need to be defined ahead of their use in the translation unit before being called during compile, otherwise the compiler would have to make a multiple passes just to "link" constant expressions for evaluation.I just wanted to add that even though this may not be good practice and will restrict you to defining the class body in the same compilation unit that its declared, it's possible to force the compiler to compile the definition of the function bodies at the same point as its declaration by adding a redundant template parameter:
Apparently it's not even a bug, because its status is
RESOLVED INVALID
, which means that the people behind GCC and that bugzilla, after reviewing the problem, don't think that this is a GCC bug.I remind you on that page because there is also an answer for this behaviour in one of the related posts.