在另一个函数内部提前声明一个`constexpr`函数——编译器bug?

9

在为我遇到的这个问题制作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

哪个编译器是正确的?

1
标准似乎不是很清楚。我们需要一位强有力的律师在这里 :) - Arunmu
1个回答

2
inline函数替换constexpr函数会保留完全相同的问题(对于全局声明1来说没问题,但对于函数作用域声明2则不行)。由于constexpr意味着inline,所以这似乎是原因。
在此情况下,对于声明2,GCC会发出警告: warning: 'inline' specifier invalid for function 'f' declared out of global scopewarning: 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没有类似的规定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接