Que*_*tin 9 c++ language-lawyer compiler-bug function-declaration constexpr
虽然我偶然发现了这个问题的MCVE ,但我发现编译器之间存在以下差异:
请考虑以下代码:
// constexpr int f(); // 1
constexpr int g() {
constexpr int f(); // 2
return f();
}
constexpr int f() {
return 42;
}
int main() {
constexpr int i = g();
return i;
}
Run Code Online (Sandbox Code Playgroud)
此代码在Clang 3.8.0上编译,但在GCC 6.1.0上失败:
error: 'constexpr int f()' used before its definition
Run Code Online (Sandbox Code Playgroud)
在两个编译器上评论// 2和取消注释// 1.
有趣的是,移动f的定义代替了// 1编译,但在// 2以下情况下触发了警告:
warning: inline function 'constexpr int f()' used but never defined
Run Code Online (Sandbox Code Playgroud)
哪个编译器是对的?
constexpr用函数替换函数inline会保留完全相同的问题(全局声明 1 可以,但函数范围声明 2 不行。)Sinceconstexpr暗示inline这似乎是原因。
在这种情况下,对于声明 2,GCC 会抱怨:\n warning: \'inline\' specifier invalid for function \'f\' declared out of global scope\nand warning: inline function \'int f()\' used but never defined。\n它无法链接 (" undefined reference to \'f()\'")。
所以看起来它放弃了内联,进行了调用,但不费心发出代码,因为f()所有使用都是内联的(?),所以链接失败。
Clang 抱怨道:\nerror: inline declaration of \'f\' not allowed in block scope
既然constexpr暗示了inline,似乎块作用域中不允许内联声明的规则也应该适用于constexpr,因此 GCC 是正确的。但标准似乎并没有出来这么说。在我检查的草案中,有关的规则inline位于 \xc2\xa77.1.2 [dcl.fct.spec],第 3 部分:“内联说明符不得出现在块作用域函数声明中”,但没有出现类似的内容constexpr。