如果函数在类范围内声明,constexpr不工作

iam*_*ind 16 c++ compiler-errors g++ constexpr c++11

我使用的是g ++ 4.8.0,它不包含早期的constexprbug.因此下面的代码工作正常:

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

int main () {}
Run Code Online (Sandbox Code Playgroud)

但是,如果我将变量括在一个classas中static,那么它会给出编译器错误:

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

int main () {}
Run Code Online (Sandbox Code Playgroud)

这是错误:

错误:数组'array'的大小不是整数常量表达式

禁止以constexpr这种方式使用还是使用另一个g ++ bug?

And*_*zos 23

是的,它是不正确的.原因如下:

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
Run Code Online (Sandbox Code Playgroud)

类说明符中的函数定义(以及初始化函数和默认参数)本质上是按类在类外定义的顺序进行解析的.

所以这:

struct X {
  constexpr static int size() { return 5; }
  static const int array[size()]; 
};
Run Code Online (Sandbox Code Playgroud)

按此顺序解析:

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

constexpr inline int X::size() { return 5; }
Run Code Online (Sandbox Code Playgroud)

也就是说,函数体的解析被推迟到类说明符之后.

这个函数体解析的推迟的目的是使函数体可以转发那时尚未声明的引用类成员,并且因此它们可以使用它们自己的类作为完整类型:

struct X
{
    void f() { T t; /* OK */ }
    typedef int T;
};
Run Code Online (Sandbox Code Playgroud)

与命名空间范围相比:

void f() { T t; /* error, T not declared */ }
typedef int T;
Run Code Online (Sandbox Code Playgroud)

POINT A,编译器还没有定义size(),所以它无法调用它.对于编译时性能constexpr,在编译期间调用之前需要先在翻译单元中使用函数定义函数,否则编译器必须进行多次传递才能"链接"常量表达式以进行评估.

  • +1 的详细解释,但我相信这更多是标准的限制。例如,如果全局函数在使用前声明并在文件末尾定义,在这种情况下编译器会给出相同的错误。为什么编译器不能对 `static` 成员也应用相同的策略。如果按照我的代码中提到的定义,则允许使用它,否则给出错误。 (2认同)

use*_*816 7

显然它甚至不是一个bug,因为它的状态是RESOLVED INVALID,这意味着GCC背后的人和bugzilla在审查问题后,并不认为这是一个GCC错误.

我在该页面上提醒您,因为在其中一个相关帖子中也有这种行为的答案.