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

What does [decl.constexpr].5 mean exactly?

constexpr 函数 的标准在 [decl.constexpr] 的第 5 点中指出:

For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required.

下面继续举例说明:

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

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

constexpr int g() { return 0; }       // ill-formed?

如果是,这背后的基本原理是什么,如果不是,那么限定是什么意思/constexpr 函数什么时候变成病式的?


大概下面这些都可以吧?

constexpr int h(int x) { return x; }  // presumably fine?
constexpr int l = h(42);              // also fine

此规则的基本原理是应该有 至少一个 上下文,其中可以在 constexpr 上下文中计算函数。例如给定:

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

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

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

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

constexpr int f() { return f(false); }   // ok

那会很好,因为评估以 core-constant-expression.

结束

同理,这个函数:

constexpr int g() { return 0; }      // ok

还有这个:

constexpr int h(int x) { return x; }  // ok
constexpr int l = h(42);              // ok

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

的措辞“......如果不存在这样的参数值......” 可能会造成混淆,因为你已经问过 [= 的格式是否正确19=]。但是 g 可以用零参数调用,或者换句话说,用 void 参数调用,所以没问题。