"constexpr"函数在另一个函数中的前向声明--编译器错误

Forward-declaration of a `constexpr` function inside another function -- Compiler bug?

本文关键字:函数 quot 声明 编译器 错误 constexpr 另一个      更新时间:2023-10-16

在为我偶然发现的这个问题生成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;
}

此代码在Clang 3.8.0上编译,但在GCC 6.1.0上失败,错误代码为:

error: 'constexpr int f()' used before its definition

注释掉// 2和取消注释// 1对这两个编译器都有效。

有趣的是,将f的定义替换为// 1会编译,但会在// 2:处触发警告

warning: inline function 'constexpr int f()' used but never defined

哪个编译器是对的?

inline函数替换constexpr函数保留了完全相同的问题(全局声明1可以,但函数范围声明2不行。)由于constexpr暗示inline,这似乎是原因。

在这种情况下,对于声明2,GCC会抱怨:warning: 'inline' specifier invalid for function 'f' declared out of global scope以及CCD_ 11。无法链接("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没有类似的内容。