[decl.constexpr].5 到底是什么意思?

bit*_*ask 3 c++ language-lawyer constexpr constexpr-function

constexpr 函数的标准在[decl.constexpr] 的第 5 点下说明:

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

它继续为此提供以下示例:

constexpr int f(bool b){ return b ? throw 0 : 0; }  // OK
constexpr int f() { return f(true); }               // ill-formed, no diagnostic required
Run Code Online (Sandbox Code Playgroud)

我从中得到的是,带有空参数列表的函数是非诊断格式错误的。这让我觉得非常奇怪,以至于我怀疑我的理解是不正确的。例如,这是否也是格式错误的:

constexpr int g() { return 0; }       // ill-formed?
Run Code Online (Sandbox Code Playgroud)

如果是这样,这背后的基本原理是什么,如果不是,则限定意味着什么/ constexpr 函数何时变得格式错误?


想必以下这些都可以吧?

constexpr int h(int x) { return x; }  // presumably fine?
constexpr int l = h(42);              // also fine
Run Code Online (Sandbox Code Playgroud)

cig*_*ien 6

这条规则的基本原理是应该至少有一个上下文可以上下文中评估函数constexpr。例如给出:

constexpr int f(bool b){ return b ? throw 0 : 0; }  // OK
constexpr int f() { return f(true); }               // ill-formed, no diagnostic required
Run Code Online (Sandbox Code Playgroud)

无法f()constexpr上下文中调用,因为通过此函数的所有路径都将以不是核心常量 expression 的表达式结束

编译器必须评估所有可能的调用,以查看该函数是否可以在constexpr上下文中使用。这通常不容易诊断,所以语言说它格式错误,不需要诊断,即你做错了什么,但编译器无法诊断它。

请注意,如果 的零参数重载f如下:

constexpr int f() { return f(false); }   // ok
Run Code Online (Sandbox Code Playgroud)

那完全没问题,因为评估以core-constant-expression 结束

同样,这个函数:

constexpr int g() { return 0; }      // ok
Run Code Online (Sandbox Code Playgroud)

还有这个:

constexpr int h(int x) { return x; }  // ok
constexpr int l = h(42);              // ok
Run Code Online (Sandbox Code Playgroud)

很好,因为gh可以在constexpr上下文中调用。

“...如果没有参数值存在这样...”的措辞可能会令人困惑,因为您已经询问了g. 但是g可以用零个参数调用,或者换句话说,用一个void参数调用,所以没问题。