【问题标题】:Initialization of a constexpr variableconstexpr 变量的初始化
【发布时间】:2019-12-14 22:27:25
【问题描述】:

[dcl.constexpr] p10 sentence 3 说:

在任何 constexpr 变量声明中,初始化的完整表达式应为 constant expression

但是,在此声明中:

constexpr int a = 10;
constexpr int b = a;

a 不是常量表达式,因为它是 glvalue 核心常量表达式,但不是permitted result of a constant expression,因为它没有静态存储持续时间,也不是临时对象。

但是,随着左值到右值转换的应用,它将变成一个常量表达式。那么是不是说初始化器不需要是常量表达式,只需要转换后的最终结果呢?

【问题讨论】:

  • 没有定义完整表达式的值类别似乎是标准的缺陷。

标签: c++ initialization language-lawyer constexpr constant-expression


【解决方案1】:

在您引用的链接中,请参阅第 10 点:

常量表达式要么是一个泛左值核心常量表达式,它引用一个作为常量表达式(如下定义)的允许结果的实体,要么是一个纯右值核心常量表达式,其值满足以下约束:

您的问题集中在 glvalue 分支下的“常量表达式的允许结果”;但是在您的示例中,它是另一个适用的分支“prvalue 核心常量表达式”。这可以应用,因为 [conv.lval]/1,

非函数、非数组类型 T 的泛左值可以转换为纯右值

我同意这有点令人困惑,这里的“prvalue 核心常量表达式”包括满足条件的 glvalues 的左值到右值转换结果的情况;而在标准“prvalue”中的其他一些地方则排除了这种情况。

【讨论】:

  • 也许我误解了什么是完整表达式,特别是当措辞说转换是“完整表达式的一部分”时。完整表达式是一个表达式,因此如果转换是该表达式的一部分,这是否意味着内部表达式有效地“嵌套”在转换内部,因此当评估完整表达式时,它是应用了该转换的嵌套表达式结果呢?
  • @KrystianS 我认为关于“初始化的完整表达式”的部分是说初始化器(在应用任何转换之后)应该是一个常量表达式
  • 好的,那么完整表达式的一个好的定义是“完整表达式是执行语句时评估的最外层表达式或转换”?
  • 其实,不,不可能,因为完整表达式不一定是单个表达式。
  • 标准定义了full-expression,可以参考一下
【解决方案2】:

“完整表达”一词是一个已定义的术语。值得注意的是 ([intro.execution]/5)

为了满足表达式出现的语言结构的要求而应用于表达式结果的转换也被视为完整表达式的一部分。

所以是的,既然要求说“初始化的完整表达式应该是一个常量表达式”,它只意味着完整表达式(包括转换),而不是其他任何东西,必须是常量表达式。

【讨论】:

  • 这不是问题——而是什么是“初始化”?显然它包括转换,但它包括初始化程序吗?初始化器的完整表达式是它本身,以及应用的任何其他转换,但不清楚“初始化”是否包括初始化器表达式本身。
  • @KrystianS 完整的表达式只是初始化器中的一个。
  • @L.F.好的,但是在我在问题a is not a constant expression 中展示的示例中
  • @KrystianS a 绝对是一个常量表达式。如果 constexpr 变量不是常量表达式,可能是什么?
  • @L.F.我认为措辞是有道理的(但是,初始化可能是初始化程序的错字),问题是我如何解释完整的表达式是什么。由于转换被认为是完整表达式的一部分,这是否意味着初始化程序有效地“嵌套”在转换内部,因此在评估完整表达式时,其结果是封闭转换的结果。
猜你喜欢
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 2015-10-21
  • 1970-01-01
  • 2011-12-23
  • 2021-08-07
  • 2015-10-10
  • 1970-01-01
相关资源
最近更新 更多