这段代码中的表达式b
应该是一个核心常量表达式
int main()
{
constexpr int a = 10;
const int &b = a;
constexpr int c = b; // here
return 0;
}
因为标准说(8.20,第 2 段 [expr.const] in n4700)
An expression
e
is a core constant expression unless the evaluation ofe
would evaluate one of the following expressions:
...
an lvalue-to-rvalue conversion (7.1) unless it is applied to
...
a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable subobject of such an object, or
首先,上面代码中的表达式 b
是一个左值(也是一个左值),因为它是一个引用,因此是一个变量(8.1.4.1,第 1 段)
[expr.prim.id.unqual]):
The expression is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise; it is a bit-field if the identifier designates a bit-field (11.5).
其次,变量b
表示的对象是a
,用constexpr
声明。但是,gcc 提示
./hello.cpp: In function ‘int main()’:
./hello.cpp:6:20: error: the value of ‘b’ is not usable in a constant expression
constexpr int c = b;
^
./hello.cpp:5:13: note: ‘b’ was not declared ‘constexpr’
const int &b = a;
据我所知,引用不是对象, 所以上面的项目符号显然暗示 a
应该用 constexpr
声明>。我错过了什么吗?我不同意 gcc 的原因是 gcc 将 b
视为一个对象,因此需要用 constexpr
声明它。但是,b
不是对象!
最佳答案
核心常量表达式的规则之一是我们 can't evaluate :
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 or
- its lifetime began within the evaluation of e;
b
是一个 id-expression,它引用了一个具有前面初始化的引用类型的变量。但是,它是从 a
初始化的。 a
是常量表达式吗?来自 [expr.const]/6 :
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints: [... ]
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.
a
是一个 glvalue 核心常量表达式(它没有遇到 expr.const/2 中的任何限制),但是它不是一个静态对象储存期限。也不是函数。
因此,a
不是常量表达式。因此,b
不是从常量表达式初始化的,因此不能在核心常量表达式中使用。因此 c
的初始化是不正确的,因为它不是一个常量表达式。将a
声明为static constexpr int
,gcc和clang都接受程序。
C++,你这个神奇的野兽。
关于c++ - 为什么这个表达式不是常量表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47908885/