c++ - 为什么这个表达式不是常量表达式?

标签 c++ language-lawyer c++17

这段代码中的表达式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 of e 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/

相关文章:

java - 高效的模 3 运算?

c++ - OpenCV findContours,如何检查两侧的颜色

c++ - 为什么带逗号的三元运算符在真实情况下只计算一个表达式?

c++ - C++17 中 malloc 返回 "invalid pointer value"吗?

c - GCC:在获取地址时取消引用 ‘void *’ 指针

c++ - 转发引用和正常引用的部分排序与推导指南

c++ - 奇怪的错误: label 'loopend' used but not defined, expected unqualified-id before “if ” (same error for “goto” and “' }' token ”

c++ - 添加该行的所有总和

c++ - sized operator delete[] 永远不会被调用

c++ - 如何在循环线程中使用 wait_for?