3

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

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

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

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


大概下面的都可以吧?

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

1 回答 1

6

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

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

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

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

请注意,如果 的零参数重载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

很好,因为g并且h可以在constexpr上下文中调用。

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

于 2020-06-11T15:26:57.530 回答