【问题标题】:What does [decl.constexpr].5 mean exactly?[decl.constexpr].5 到底是什么意思?
【发布时间】:2020-10-01 06:58:55
【问题描述】:

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

【问题讨论】:

  • 这是由 chat discussion 引发的。我想其他人可以加入该聊天。
  • 模板也有类似的规则,模板应该具有可实例化的潜在类型/参数(禁止static_assert(false);)。

标签: c++ language-lawyer constexpr constexpr-function


【解决方案1】:

此规则的基本原理是应该有至少一个上下文,函数可以在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 上下文中使用。这通常不容易诊断,所以语言说它是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

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

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

【讨论】:

  • 那么,如果要删除原始示例中的throw,那又可以了,对吗?
  • 是的,如果 bool 重载也可以使用 false 的参数调用。
  • @bitmask - 嗯,这取决于你用什么替换它
  • 将其添加到答案中。是的,您需要将 throw 替换为 core-constant-expression 才能调用 f(true)
猜你喜欢
  • 2017-08-07
  • 2017-07-20
  • 2014-09-23
  • 2014-07-25
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多