以下代码只能在 GCC 上编译(在 godbolt.org 上检查了 10.4 和 13.2),但不能在 Clang 上编译(在我尝试过的所有版本上都失败,例如 godbolt.org 上的 17.1):
struct A {
static constexpr int b{1};
};
int main(int argc, char *argv[]) {
A a;
A& aref{a};
constexpr auto bb1{a.b};
constexpr auto bb2{aref.b};
return bb1+bb2;
}
Clang 输出:
<source>:9:20: error: constexpr variable 'bb2' must be initialized by a constant expression
9 | constexpr auto bb2{aref.b};
| ^ ~~~~~~~~
<source>:9:24: note: initializer of 'aref' is not a constant expression
9 | constexpr auto bb2{aref.b};
| ^
<source>:7:14: note: declared here
7 | A& aref{a};
|
https://godbolt.org/z/nG4j3KefE
为什么?
这是一个很好的问题,我觉得这个问题和这个有类似的“物种”。最后一个答案(对这个问题)有一条评论,指出 gcc 无法识别错误,这是贯穿上述答案的主题。 你的问题的答案可能只是一个平淡无奇的“clang 比 gcc 更紧密地遵循 C++ 标准”。我相信每个人都知道编写编译器绝非易事,有些语法只是逃避了标记器/开发团队等。再加上完成软件的下行压力,GCC 团队无法涵盖所有内容当前 C++ 标准以及 LLVM 团队的各个方面。
引用这篇文章(接近结尾):“Clang和LLVM比GCC更严格地遵守C和C++标准。GCC升级过程中不会出现GNU Inline等问题。”
这是一个不那么平淡的答案。
如果
A a;
是全局的,即在 main() 之前声明,clang 版本也会编译,因为任何引用都不会是本地对象,因此可能是 const (对于 constexpr)。对本地对象的引用(即使在 main() 中也不被视为 const)