在类嵌套静态常量成员变量初始化 Clang vs GCC 哪个编译器是正确的
In class nested static const member variable initialization Clang vs GCC which compiler is right?
考虑以下代码段:
#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 会发出错误:
错误:未在此范围内声明"i"
现场演示
问:
两个编译器中哪一个符合C++标准?
GCC 抱怨名称未声明当然是错误的,因为i
的声明点紧随其声明符之后。
但是,GCC 总体上拒绝该代码段可以说是正确的。[class.static.data]/3:
如果非易失性
const
静态数据成员是整数或 枚举类型,它在类定义中的声明可以指定 大括号或等于初始值设定项,其中每个初始值设定项 这是一个赋值 - 表达式是一个常量表达式 (5.20)。
为了使 [expr.const]/(2.7) 不失败,其四个子项目符号之一必须适用:
左值到重值的转换 (4.1),除非它应用于
- 整数或枚举类型的非易失性 gl值,指的是具有前面的完整非易失性
const
对象 初始化,使用常量表达式初始化,或- 引用字符串文本 (2.13.5) 的子对象的非易失性 gl值,或
一个非易失性- gl值,它指的是用
constexpr
定义的非易失性对象,或者指的是这样一个 对象,或- 文字类型的非易失性 gl值,指的是其生命周期始于
e
评估的非易失性对象;
(2.7.1) 是唯一合理的候选者,但由于 i
以前没有使用初始值设定项进行初始化,因此它不适用。
请注意,Clang 是完全一致的:
constexpr int i = i;
void f() {
// constexpr int j = j; // error
static constexpr int h = h;
}
如果i
具有静态存储持续时间,则它似乎将视为在其初始值设定项中"正确"初始化。我提交了错误#26858。
在类中初始化的静态 const 成员必须由常量表达式初始化。在 i
的初始值设定项中,i
还没有被常量表达式初始化,因此它本身也不是常量表达式。在我看来,两个编译器都是有罪的。
- 叮
- 叮当当,用于接受程序
- GCC,用于提供误导性错误消息
相关文章:
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 初始化迭代器错误 C++ 在 GCC 编译器中
- #pragma(*诊断)当将Clang分析器与GCC编译器混合时
- 为什么 gcc 编译器标志未知?
- 如何使用 GCC 编译器优化创建静态库?
- GCC 编译器是否应该对涉及 [[fallthrough]] 属性的格式错误的C++代码进行诊断?
- 如何在macOS中的旧扩展clang和gcc编译器中初始化数组和向量
- gcc c++编译器中的零大小数组
- 相对于继承的构造函数,gcc 编译器是否还有一个错误?
- template-id 与任何模板声明 GNU gcc 编译器都不匹配
- 关于 PBC 库在 GCC 编译器在 DEV C++ 中使用
- 选择默认的 gcc/g++ 编译器
- GCC编译器,为较低版本的GCC编译应用程序
- 相同的代码在不同的 gcc 编译器中存在巨大的性能差异
- GCC 编译器对类型转换有什么作用?为什么 mac 和 Linux 上的输出不同
- GCC 编译器错误:stl_construct.h、stl_uninitialized.h
- 如何从我的qt应用程序运行gcc编译器?
- GCC 编译器错误:stl_construct.h
- 升级 gcc 编译器/其他修复程序以向后兼容
- GCC 编译器一个字节中有多少位