【问题标题】:C++ integral constant expression definitionC++ 整数常量表达式定义
【发布时间】:2019-06-05 16:16:28
【问题描述】:

在当前的 C++ 标准中有以下段落 (expr.const#5)(强调我的):

整型常量表达式是整型或无作用域枚举类型的表达式,隐式转换为纯右值,其中转换后的表达式是核心常量表达式。 [ 注意:此类表达式可以用作位字段长度,如果基础类型不固定([dcl.enum]),则可以用作枚举器初始化器,还可以用作对齐方式。 — 尾注 ]

关于这个定义我有两个问题:

  1. 短语“隐式转换为纯右值”是否意味着要将表达式视为“整型常量表达式”,它必须出现在强制将其隐式转换为纯右值的上下文中?

  2. “转换后的表达式”指的是什么?我知道这个问题在Clarification of converted constant expression definition 中得到解决。那里给出的答案是“转换后的表达式”是t,经过以下初始化:T t = expr;。但是,我看不出评估该表达式 (t) 将如何匹配 [expr.const#4] 中给出的任何规则(描述将表达式视为核心常量表达式的必要条件的段落 em>) 这将使其无法成为核心常量表达式

谢谢。

【问题讨论】:

  • 奇怪,我认为转换后的表达式是指右值表达式,它是左值到右值转换的结果。
  • @PasserBy 对我来说,将左值到右值转换的结果称为表达式很奇怪,因为我只考虑我在程序中编写的表达式。无论如何,为了确定一个表达式是否是一个核心常量表达式,我们必须考虑在它的求值过程中会发生什么。如果“转换后的表达式”指的是作为左值到右值转换结果的纯右值表达式,那么对这种表达式的求值究竟涵盖了什么? [继续]
  • 例如,如果原始表达式是f(),其中f 被声明为int& f();,那么“转换后的表达式”的求值是否包括在函数f 内执行的语句?
  • @user42768:它被认为是一个表达式,因为诸如值类别和常量评估规则之类的东西是根据表达式定义的(并考虑有多少隐式表达式是由隐式定义的赋值引入的操作员)。是的,考虑f的内容; restrictions on constexpr 函数本身还不够强大。
  • @PasserBy:标准的disagrees关于具有值类别的值,尽管说某些表达式只有引用类型非常接近正确。

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


【解决方案1】:

整数常量表达式隐式转换为纯右值的语句意味着左值到右值的转换适用于用作整数常量表达式的任何表达式。在一个表达式可能是一个整型常量表达式的一种情况下——初始化一个可能在常量表达式中可用的 const 限定整数类型的非局部对象——初始化器无论如何都是一个纯右值,所以没有解释可能会发生变化。

除此之外,您的两个问题都有相同的答案:将表达式(如所写)转换为纯右值整数类型所需的任何转换也必须在核心常量表达式中允许(例如,参见/4.7就在您的引文之前和/6 之后)。 “转换后的表达式”包括 T t=e; 解释中的转换,而不仅仅是 id-expression t(例如,它总是一个左值)。

【讨论】:

  • 感谢您的回答。我的第一个问题是“隐式转换为纯右值”的措辞是否意味着为了使表达式被视为“整数常量表达式”,它必须在需要将其转换为纯右值的上下文中使用,不一定关于转换本身。 [继续]
  • 对于我的第二个问题,您所说的“转换表达式”的措辞是指“转换过程”。我知道在语义上它与此相关,但是(在语法上)我希望术语“转换后的表达式”指的是一个表达式(无论是“书面”还是左值到右值转换之后的那个)。
  • @user42768:我添加了一些关于prvalue转换情况的解释。至于表达式,它是写出来的表达式,给定特定的上下文解释(对于if 条件,它可能会调用operator bool)。
  • “初始化器无论如何都是纯右值”,对吧? constexpr int i = 42; constexpr int j = i; 不是纯右值初始化器,但应用 l-t-r 的结果是。
  • @DavisHerring 所以你说“转换后的表达式”是指原始表达式加上使用它的上下文,这意味着“转换后的表达式”的评估包括对原始表达式以及所需转换的评估。
【解决方案2】:

我查看了clang的源代码,特别是“SemaOverload.cpp”中的函数“CheckConvertedConstantExpression”。在那里执行的操作如下:

  1. 找到所需的隐式转换序列
  2. 检查是否仅使用http://eel.is/c++draft/expr.const#7 中列出的转化
  3. 执行隐式转换(在这一步我相信会创建一个新表达式,例如,如果原始表达式是f(),它是A 类类型,具有用户定义的int 转换函数,并且上下文需要int,那么新的表达式应该是f().operator int())
  4. 检查是否需要缩小转换
  5. 评估第 3 步生成的表达式(隐式检查它是否为 constant expression

所以我相信,正如@Davis Herring 的answer 中所述,术语“转换后的表达式”是指一个新的表达式,其评估包括对程序中所写的原始表达式的评估,以及对任何需要转换。

【讨论】:

    猜你喜欢
    • 2017-03-30
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 2011-06-30
    • 2016-03-01
    • 2018-09-03
    相关资源
    最近更新 更多