我正在使用g++ 4.8.0,其中不包含早期的constexpr错误。因此下面的代码可以工作fine:

constexpr int size() { return 5; }
int array[size()];

int main () {}

但是,如果我将两个变量都包含在class中作为static,则它给出compiler error:
struct X {
  constexpr static int size() { return 5; }
  static const int array[size()];
};

int main () {}

这是错误:



是否禁止以这种方式使用constexpr或另一个g++错误?

最佳答案

是的,它格式不正确。原因如下:

在常量表达式中使用constexpr函数之前,需要先对其进行定义(而不是声明)。

因此,例如:

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

类说明符内的函数定义(以及初始化程序和默认参数)实际上是按照在类外部定义的顺序进行解析的。

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

按以下顺序解析:
struct X {
   constexpr inline static int size(); // function body defered
   static const int array[size()];  // <--- POINT A
};

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

即,将函数体的解析推迟到类说明符之后。

推迟进行函数体解析的目的是,使函数体可以转发当时尚未声明的引用类成员,并且还可以将自己的类用作完整类型:
struct X
{
    void f() { T t; /* OK */ }
    typedef int T;
};

与命名空间范围相比:
void f() { T t; /* error, T not declared */ }
typedef int T;

POINT A处,编译器尚没有size()的定义,因此无法调用它。为了获得编译时性能,需要在转换单元中使用constexpr函数之前先定义ojit_code函数,然后在编译过程中对其进行调用,否则编译器将不得不进行多次遍历,才能“链接”常量表达式以进行评估。

09-10 03:49
查看更多