c++ - 下面的代码,是格式错误的 NDR 还是格式正确?

标签 c++ language-lawyer c++17 constexpr

Clang 接受以下代码,但 gcc rejects it .

void h() { }

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

int main() {
    constexpr int i = f();
}

这是错误信息:

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();

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

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

最佳答案

Clang 是正确的。对 f() 的调用是一个常量表达式,因为对 h() 的调用永远不会被计算,因此 [dcl.constexpr]/5 不适用。在 f() 的主体中对 h() 的调用不是格式错误的,因为 constraints关于 constexpr 函数并没有说明不允许调用非 constexpr 函数。事实上,像下面这样的函数是格式良好的,因为当 x 为奇数时,对它的调用可以是一个常量表达式:

constexpr int g(int x) {
    if (x%2 == 0) h();
    return 0;
}

关于c++ - 下面的代码,是格式错误的 NDR 还是格式正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55752281/

相关文章:

c++ - 在 boost::compute 中分配大 vector

c++ - C'tor 的类型转换不起作用

C++ offsetof char* 算法

c++ - 数组元素算作一个共同的初始序列吗?

c++ - 在 C++17 中使用 SFINAE 和模板回退 "std::ostream"和 "<<"运算符

c++ - 注册回调函数后出现段错误

c++ - 不明确的成员访问表达式 : is Clang rejecting valid code?

c++ - 在 constexpr 函数中实例化多个模板

c++ - 准备废弃 std::iterator

c++ - 无法编译简单的C++17程序