GCC是否正确要求这个引用声明的constexpr说明符? [英] Is GCC correct in requiring the constexpr specifier for this reference declaration?
问题描述
下面的代码不会在 GCC 5.3.0 下编译,因为 r
缺少一个 constexpr
说明符。
The code below doesn't compile under GCC 5.3.0 because the declaration of r
is missing a constexpr
specifier.
const int i = 1;
const int& r = i;
constexpr int j = r;
我相信拒绝是正确的。
I believe the rejection is correct. How do I prove it using the working draft N4527?
推荐答案
首先,因为我们使用了一个引用,[expr.const ] /(2.9)不得违反。 (2.9.1)适用,但:
First, since we're using a reference, [expr.const]/(2.9) must not be violated. (2.9.1) applies, though:
一个指向变量或数据成员的
引用类型,除非引用具有先前的初始化和
。
- 使用常量表达式初始化
an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either
— it is initialized with a constant expression
p只要初始化程序 - i
- 是一个常数表达式(如下所示),使用 r
还需要检查第3行中的ltr转换是否合法,即(2.7)不得违反。然而,(2.7.1)适用于:
I.e. using r
is fine, as long as the initializer - i
- is a constant expression (this is shown below).
It's also necessary to check whether the l-t-r conversion in line 3 is legal, i.e. (2.7) must not be violated. However, (2.7.1) applies:
一个左值到右值的转换(4.1),除非它应用于
- a
指向
a的整数或枚举类型的非易失性glvalue完成非易失性const
对象,具有前面的
初始化,初始化用常量表达式,或者
an lvalue-to-rvalue conversion (4.1) unless it is applied to
— a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatileconst
object with a preceding initialization, initialized with a constant expression, or
...这样也很好,因为(g)lvalue是 r
,它指的是 i
- 它是一个非易失性的 const
常量表达式初始化( 1
)。
…so that's fine as well, since the (g)lvalue is r
, and it refers to i
- which is a non-volatile const
object with a constant expression initializer (1
).
我们推迟了显示 i
实际上是一个常量表达式,一旦这样,我们需要显示 r
是一个常数表达式。
[expr.const] / 5适用于:
We postponed showing that i
is actually a constant expression, and once that's out of the way, we need to show that r
is a constant expression.
[expr.const]/5 pertains to that:
常量表达式是一个glvalue核心常量表达式
,其值指向一个实体,该实体是
常量的允许结果表达式(如下定义)或prvalue核心常量
表达式,其值为对象及其
子对象的对象:
A constant expression is either a glvalue core constant expression whose value refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value is an object where, for that object and its subobjects:
- 引用类型的每个非静态数据成员引用一个常量表达式允许的结果的实体,如果对象或子对象是指针,则
- 类型,它包含具有静态存储持续时间的对象的地址,地址过去
这样的对象的结束(5.7),函数的地址或空的
指针值。
如果实体是静态存储持续时间为$ b的对象,则该实体是常量表达式的允许结果 $ b不是临时对象,也不是一个临时对象,其值满足上述约束,或者是一个
函数。
An entity is a permitted result of a constant expression if it is an object with static storage duration that is either not a temporary object or is a temporary object whose value satisfies the above constraints, or it is a function.
由于 i
在上述上下文中是一个(g)lvalue,它必须是一个常量表达式的允许结果,因为它具有静态存储持续时间,当然不是暂时的。因此 i
是一个常数表达式。
Since i
is, in the above context, a (g)lvalue, it has to be a permitted result of a constant expression - which it is, since it has static storage duration and certainly isn't a temporary. Thus i
is a constant expression.
r
,因为我们已经确定 r
是一个核心常量表达式,我们只需要检查项目符号。
r
is, however, treated as a prvalue in line 3. Since we already established that r
is a core constant expression, we solely need to check the bullet points. They're clearly met, though.
因此代码在命名空间范围中格式化。它不会在局部范围内,因为 i
不再是常量表达式的允许结果。 Clang提供了全面的错误讯息。
Hence the code is well-formed in namespace scope. It won't be in local scope, as i
wouldn't be a permitted result of a constant expression anymore. Clang gives a comprehensive error message.
这篇关于GCC是否正确要求这个引用声明的constexpr说明符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!