我使用的是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 () {}
这是错误:
错误:数组'array'的大小不是整数常量表达式
是否禁止以这种方式使用constexpr
或另一个g ++错误?
答案 0 :(得分:22)
是的,它是不正确的。原因如下:
在用于常量表达式之前,需要定义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
函数需要在编译期间调用之前在翻译单元中使用之前进行定义,否则编译器必须进行多次传递才能“链接”常量表达式以进行评估。 / p>
答案 1 :(得分:7)
显然是it's not even a bug,因为它的状态为RESOLVED INVALID
,这意味着GCC背后的人和bugzilla在审核问题后,并不认为这是GCC错误。
我在该页面上提醒您,因为在其中一个相关帖子中也有这种行为的答案。
答案 2 :(得分:1)
我只是想补充一点,即使这可能不是一个好习惯,并且将限制您在其声明的同一编译单元中定义类主体,也可以强制编译器在以下位置编译功能主体的定义:通过添加冗余模板参数与声明相同:
"date.h"