在为this问题产生MCVE时我偶然发现,我发现编译器之间存在以下差异:
请考虑以下代码:
Global.asax
此代码在Clang 3.8.0上编译,但在GCC 6.1.0上失败:
// 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;
}
评论error: 'constexpr int f()' used before its definition
并取消注释// 2
适用于两个编译器。
有趣的是,移动// 1
的定义代替f
编译,但会在// 1
处触发警告:
// 2
哪种编译器是对的?
答案 0 :(得分:2)
用constexpr
函数替换inline
函数会保留完全相同的问题(可以使用全局声明1,但不能使用函数范围声明2.)自constexpr
以来暗示inline
这似乎是原因。
在这种情况下,通过声明2,海湾合作委员会抱怨:
warning: 'inline' specifier invalid for function 'f' declared out of global scope
和warning: inline function 'int f()' used but never defined
。
它无法链接(“undefined reference to 'f()'
”)。
所以它似乎放弃了内联,放入了一个调用,但是没有为f()
发出代码,因为所有用法都是内联的(?),所以链接失败了。
和Clang抱怨说:
error: inline declaration of 'f' not allowed in block scope
由于constexpr
暗示inline
,所以在块范围内不允许内联声明的规则似乎也适用于constexpr
,因此GCC是正确的。但标准似乎没有出来说这个。在我检查的草案中,关于inline
的规则在§7.1.2[dcl.fct.spec]中,第3部分:“内联说明符不应出现在块作用域函数声明中”,但没有出现类似内容关于constexpr
。