GCC要求此引用声明使用constexpr说明符是否正确

Is GCC correct in requiring the constexpr specifier for this reference declaration?

本文关键字:说明符 constexpr 是否 引用 声明 GCC      更新时间:2023-10-16

下面的代码没有在GCC 5.3.0下编译,因为r的声明缺少constexpr说明符。

const int i = 1;
const int& r = i;
constexpr int j = r;

我相信拒绝是正确的。如何使用工作草案N4527来证明它?

首先,由于我们使用的是引用,因此不能违反[expr.const]/(2.9)。(2.9.1)适用,不过:

引用的变量或数据成员的id表达式引用类型,除非该引用具有先前的初始化,并且
-使用常量表达式初始化

也就是说,只要初始化器i-是一个常量表达式(如下所示),使用r就可以了
还需要检查第3行中的l-t-r转换是否合法,即不得违反(2.7)。但是,(2.7.1)适用:

左值到右值的转换(4.1),除非它应用于
--a引用的整数或枚举类型的非易失性glvalue一个完整的非易失性const对象初始化,用常量表达式或初始化

…这也很好,因为(g)左值是r,它指的是i-这是一个非易失性const对象,具有常量表达式初始值设定项(1)。

我们推迟了证明i实际上是一个常数表达式的时间,一旦解决了这个问题,我们就需要证明r是一个常量表达式
[expr.const]/5与此相关:

常量表达式是glvalue核心常量表达式其值指的是一个实体,该实体是常量表达式(定义如下),或prvalue核心常量其值为对象的表达式,其中,对于该对象及其子对象:

  • 引用类型的每个非静态数据成员都引用了一个实体,该实体是常量表达式的允许结果,并且
  • 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,即过去的地址此类对象(5.7)的结尾、函数的地址或null指针值

如果实体是静态存储持续时间为要么不是临时对象,要么是值满足上述约束的临时对象,或者是作用

由于i在上面的上下文中是一个(g)左值,它必须是常量表达式的允许结果——事实就是这样,因为它有静态存储持续时间,当然不是临时的。因此CCD_ 13是一个常数表达式。

然而,r在第3行中被视为一个prvalue。由于我们已经确定r是一个核心常量表达式,因此我们只需要检查要点。不过,他们显然相遇了。

因此,代码在命名空间范围内是格式良好的。它将不在局部范围内,因为i将不再是常量表达式的允许结果。Clang给出了一个全面的错误信息。