格式错误,无需诊断(NDR):C ++ 14中抛出了ConstExpr函数

J L*_*J L 3 c++ throw constexpr c++14

#include <iostream>
using namespace std;

constexpr int f(bool b){ return b ? throw 0 : 0; } // OK 

constexpr int f() { return f(true); } // Ill-Formed, No Diagnostic Required

int main(){

    try{
        f();
    }catch( int x ){
        cout << "x = " << x << endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该代码是C ++ 14标准(ISO / IEC 14882:2014)第7.1.5节第5段的示例:

对于非模板,非默认constexpr函数或非模板,非默认,非继承constexpr构造函数,如果不存在参数值,则该函数或构造函数的调用可以是核心常量的评估子表达式表达式(5.19),程序格式错误;无需诊断。

它被描述为“ 格式错误,不需要诊断 ”,因为throw-expression不是核心常量表达式(5.19 / 2)。但是,Clang和GCC都可以成功编译它(Ideone)。

  • 此代码正确(标准中有错误)还是不正确(Clang和GCC中都存在错误)?

我还发现了有关标准措辞的这些有趣的讨论:

一个/该程序是否可能“ 格式错误,不需要诊断 ”,并且允许编译器成功编译该程序?

eer*_*ika 5

这段代码是否正确(标准中有错误)

标准是决定程序是否“正确”(即格式正确)的因素。该标准明确指出该程序格式错误。

还是不正确(Clang和GCC中都存在错误)?

程序格式错误(错误)。clang和gcc的行为均符合标准。

一个程序/该程序是否可能“格式错误,无需诊断”,并且允许编译器成功编译该程序?

是。该标准不要求格式错误的程序必须无法编译。如果程序违反规则,则仅要求实现至少发出一条诊断消息。某些规则不可诊断,如果违反了某些规则,则无需进行诊断。

实际上,该规则被认为是“不可诊断的”,因为(通常)编译器很难证明违反了该规则。非常成功地编译“无需诊断”规则冲突。

如果格式错误的程序确实可以编译,则该标准未指定此类程序应如何运行。