Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
373 views
Welcome To Ask or Share your Answers For Others

1 Answer

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:

constexpr int f(); // declare f
constexpr int x = f(); // use f - ILLEGAL, f not defined
constexpr int f() { return 5; } // define f, too late

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:

struct X {
  constexpr static int size() { return 5; }
  static const int array[size()]; 
};

Is parsed in this order:

struct X {
   constexpr inline static int size(); // function body defered
   static const int array[size()];  // <--- POINT A
};

constexpr inline int X::size() { return 5; }

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:

struct X
{
    void f() { T t; /* OK */ }
    typedef int T;
};

Compared to at namespace scope:

void f() { T t; /* error, T not declared */ }
typedef int T;

At POINT A, the compiler doesn't have the definition of size() yet, so it can't call it. For compile-time performance constexpr 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...