考虑以下代码:
#include <iostream>
struct Foo {
static int const i = i + 1;
};
int main() {
std::cout << Foo::i << std::endl;
}
Clang版本3.7编译并输出1
。
虽然GCC 5.3版本发出错误:
错误:&#39;我&#39;未在此范围内声明
两个编译器中的哪一个符合C ++标准?
答案 0 :(得分:4)
由于i
的声明是immediately after its declarator,因此GCC当然不应该抱怨该名称未被宣布。
然而,海湾合作委员会可以说完全拒绝整个片段。 [class.static.data]/3:
如果非易失性
const
静态数据成员是完整的或 枚举类型,它在类定义中的声明可以指定 一个大括号或等于初始化 ,其中每个初始化子句 这是一个赋值 - 表达式是一个常量表达式(5.20)。
并且[expr.const]/(2.7)不要失败,其四个子弹中的一个必须适用:
左值 - 右值转换(4.1),除非它适用于
- 一个非整数或枚举类型的非易失性glvalue,它引用一个完整的非易失性
初始化const
对象与前一个 初始化,使用常量表达式或- 一个非易失性glvalue,它引用字符串文字的子对象(2.13.5)或
- 一个非易失性glvalue,它引用一个用
constexpr
定义的非易失性对象,或者引用这种不可变的子对象。 对象,或- 文字类型的非易失性glvalue,引用一个非易失性对象,其生命周期始于
e
的评估;
(2.7.1)是唯一合理的候选者,但由于i
之前未使用初始化程序初始化,因此不适用。
请注意,Clang是completely consistent:
constexpr int i = i;
void f() {
// constexpr int j = j; // error
static constexpr int h = h;
}
它似乎将i
视为&#34;正确&#34;如果它具有静态存储持续时间,则在其初始化程序中初始化我提交了错误#26858。
答案 1 :(得分:2)
在类中初始化的静态const成员必须由常量表达式初始化。在i
的初始值设定项中,i
未通过常量表达式(尚未)初始化,因此本身不是常量表达式。在我看来,两个编译器都是有罪的。