为什么此表达式不是常量表达式? [英] Why is this expression not a constant expression?

查看:163
本文介绍了为什么此表达式不是常量表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码中的表达式b应为核心常量表达式

The expression b in this code shall be a core constant expression

int main()
{
    constexpr int a = 10;
    const int &b = a;
    constexpr int c = b; // here
    return 0;
}

因为该标准说(8.20,第2段[expr.const]在

since the standard says (8.20, paragraph 2 [expr.const] in n4700)

表达式e核心常量表达式,除非对 e将计算以下表达式之一:

An expression e is a core constant expression unless the evaluation of e would evaluate one of the following expressions:

  • ...

  • ...

左值到右值转换(7.1),除非将其应用于

an lvalue-to-rvalue conversion (7.1) unless it is applied to

  • ...

  • ...

非易失性glvalue ,它引用用constexpr定义的非易失性对象,或引用此类对象的非可变子对象或

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是左值(也是glvalue),因为它是引用,因此是变量(8.1.4.1,第1段) [expr.prim.id.unqual]):

First, the expression b in the above code is an lvalue (which is also a glvalue) since it's a reference, thereby being a variable (8.1.4.1, paragraph 1 [expr.prim.id.unqual]):

如果实体是函数,则表达式为左值, 变量,否则为数据成员和prvalue;如果标识符指定一个位字段(11.5),则为位字段.

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抱怨

Second, the object the variable b denotes is a, and it's declared with constexpr. However, gcc complains

./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不是对象!

As far as I can tell, a reference is not an object, so the above bullet apparently suggests that a shall be declared with constexpr. Am I missing something? The reason why I don't agree with gcc is that gcc sees b as an object, thereby requiring it to be declared with constexpr. However, b is not an object!

推荐答案

核心常量表达式的规则之一是,我们

One of the rules for core constant expressions is that we can't evaluate:

一个 id-expression 引用引用类型的变量或数据成员,除非引用具有前面的初始化和

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

  • 使用常量表达式或
  • 进行初始化
  • 其寿命始于e的评估;
  • it is initialized with a constant expression or
  • its lifetime began within the evaluation of e;

b id-expression ,它引用具有先前初始化的引用类型的变量.但是,它是从a初始化的. a是一个常量表达式吗?来自 [expr.const]/6 :

b is an id-expression that refers to a variable of reference type with preceding initialization. However, it is initialized from a. Is a a constant expression? From [expr.const]/6:

常量表达式是glvalue核心常量表达式,它引用的是一个常量表达式(如以下定义)的允许结果的实体,或者是其值满足以下条件的prvalue核心常量表达式:以下限制:[...]

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 is a glvalue core constant expression (it doesn't hit any of the restrictions in expr.const/2), however it is not an object with static storage duration. Nor is it a function.

因此,a不是常数表达式.结果,b并不是从常量表达式初始化的,因此不能在核心常量表达式中使用.因此,c的初始化格式不正确,因为它不是常量表达式.将a声明为static constexpr int,并且gcc和clang都接受该程序.

Hence, a is not a constant expression. And b, as a result, isn't initialized from a constant expression and so can't be used in a core constant expression. And thus c's initialization is ill-formed as not being a constant expression. Declare a as a static constexpr int, and both gcc and clang accept the program.

C ++,您是神奇的野兽.

C++, you magical beast.

这篇关于为什么此表达式不是常量表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆