下面的代码是格式错误的NDR还是格式正确的?

Ale*_*der 24 c++ language-lawyer constexpr c++17

Clang接受以下代码,但gcc 拒绝它

void h() { }

constexpr int f() {
    return 1;
    h();
}

int main() {
    constexpr int i = f();
}
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'constexpr int f()':
main.cpp:5:6: error: call to non-'constexpr' function 'void h()'
     h();
     ~^~
main.cpp: In function 'int main()':
main.cpp:9:24: error: 'constexpr int f()' called in a constant expression
     constexpr int i = f();
                       ~^~
main.cpp:9:19: warning: unused variable 'i' [-Wunused-variable]
     constexpr int i = f();
Run Code Online (Sandbox Code Playgroud)

一旦我们考虑了[dcl.constexpr] / 5,因为这f()不是一个常数表达式,因为它不满足[expr.const] /(4.2),这可能是两个编译器都是正确的情况一个非constexpr函数h。也就是说,代码格式错误,但是不需要诊断。

另一种可能性是代码格式正确,因为[expr.const] /(4.2)在这种情况下不适用,因为未评估对hin 的调用f。如果是这种情况,那gcc是错误的,clang是正确的。

Bri*_*ian 24

lang是正确的。调用f()是一个常量表达式,因为h()从未评估该调用,因此[dcl.constexpr] / 5不适用。h()主体中的to调用f()不是错误的形式,因为对函数的约束constexpr并未说明不允许其调用非constexpr函数。实际上,如下所示的函数格式正确,因为当它x为奇数时,对其的调用可以是一个常量表达式:

constexpr int g(int x) {
    if (x%2 == 0) h();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @亚历山大我不确定那部分是不清楚的。我链接了该标准的一部分,列出了禁止在constexpr函数体中出现的结构。调用非`constexpr`函数不是禁止的构造之一。但是,如果对非constexpr函数的调用不可避免(即沿所有路径发生),则[dcl.constexpr] / 5会被违反。 (5认同)