int a = 1,是|| 1个常量表达式? [英] int a=1, is a || 1 a constant expression?

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

问题描述

N4527 5.20 [expr.const] p5

N4527 5.20[expr.const]p5

常量表达式可以是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:

-每个引用类型的非静态数据成员都引用一个实体,该实体是常量表达式的允许结果,并且

— each non-static data member of reference type refers to an entity that is a permitted result of a constant expression, and

-如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,该对象末尾的地址(5.7),函数的地址或空指针值

— if the object or subobject is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value.

如果实体是具有静态存储持续时间的对象,该对象不是临时对象或者其值满足上述约束的临时对象,或者它是一个常量对象,则它是常量表达式的允许结果. 功能.

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.

void foo(){
    int a = 1;
    int b[a || 1]{};//ok in gcc 5.1.0, error in clang 3.8.0
    static_assert(a || 1,"");//ok in gcc 5.1.0, error in clang 3.8.0
    switch(1){
        case a || 1://ok in gcc 5.1.0, error in clang 3.8.0
            ;
        }
}

a || 1恒定表达式吗?

N4527 5.20 [expr.const] p2

N4527 5.20[expr.const]p2

条件表达式e是核心常数表达式,除非按照e的规则对e求值. 抽象机(1.9),将评估以下表达式之一:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

(2.7)-左值到右值的转换(4.1),除非将其应用于

(2.7) — an lvalue-to-rvalue conversion (4.1) unless it is applied to

(2.7.1)-整数或枚举类型的非易失性glvalue,它引用完整的非易失性const 具有先前初始化的对象,该对象使用常量表达式初始化,或者

(2.7.1) — a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or

(2.7.2)—引用字符串文字(2.13.5)的子对象的非易失性glvalue,或者

(2.7.2) — a non-volatile glvalue that refers to a subobject of a string literal (2.13.5), or

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

(2.7.3) — a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable sub-object of such an object, or

(2.7.4)-文字类型的非易失性glvalue,指的是生命周期开始的非易失性对象 在e的评估之内;

(2.7.4) — a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

a || 1核心常量表达式吗?

推荐答案

a不是常量表达式(请参见下面的标准引言),因此:

a is not constant expression(see standard quote below) and therefore:

a || 1 

也不是常量表达式,尽管我们知道表达式必须计算为真,标准在这里需要从左到右求值,而且我没有看到允许编译器跳过.

Is not a constant expression either, although we know the expression has to evaluate to true the standard requires left to right evaluation here and I see no exceptions that would allow the compiler to skip the lvalue-to-rvalue conversion of a.

但是:

const int a = 1;

可以用在常量表达式中,因为它属于5.20p2(强调我的)的例外情况:

Could be used in a constant expression because it fall under the exception from 5.20p2 (emphasis mine):

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

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

  • 整数或枚举类型的非易失性glvalue,它引用完整的非易失性const 具有预先初始化的对象,该对象使用常量表达式
  • 进行了初始化
  • 一个非易失性glvalue,它引用字符串文字(2.13.5)的子对象,或者
  • 非易失性glvalue,它引用用constexpr定义的非易失性对象,或引用 到此类对象的非可变子对象,或
  • 文字类型的非易失性glvalue,指的是生命周期开始的非易失性对象 在e
  • 的评估范围内
  • a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or
  • a non-volatile glvalue that refers to a subobject of a string literal (2.13.5), or
  • a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable sub-object of such an object, or
  • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e

这条规则也是为什么原始情况不是常量表达式的原因,因为没有例外适用.

This rule is also why the original case is not a constant expression since none of the exception apply.

也许gcc允许这样做:

int b[a || 1]{};

作为可变长度数组作为扩展名,尽管它应该使用-pedantic提供警告.尽管这不能解释static_assert的情况,但是它们可以是常量折叠的,但是我不认为as-if规则会将其视为常量表达式.

as a variable length array as an extension, although it should provide a warning using -pedantic. Although that would not explain the static_assert case, they could be constant folding it but I don't think the as-if rule would allow it to be considered a constant expression.

更新,可能的gcc扩展名

从此错误报告中逻辑运算符的RHS可能会使LHS的常数保持不变,表达式,这看起来像是可能的gcc扩展名:

From this bug report RHS of logical operators may render LHS unevaluated in constant-expression this looks like a possible gcc extension:

尽管在 常量表达式:

This compiles without incident, despite using a non-constant object in a constant-expression:

int i;
static_assert( i || true, "" );
static_assert( ! ( i && false ), "" );

似乎是假设||.和&&是可交换的,但是 短路仅在一个方向上起作用.

It appears to be assuming that || and && are commutative, but short-circuiting only works in one direction.

最后的评论是:

我认为这是一个有目的的语言扩展,可以使用开关禁用它.如果static_assert总是很严格,那就太好了.

I think this is a purposeful language extension, which could use a switch to disable. It would be nice if static_assert were always strict.

这似乎是一个不合格的扩展,当使用无效的-pedantic标志在中发布时,应该触发警告是一个符合标准的编译器扩展,可以将非constexpr标准库函数视为constexpr?.

This seems like a non-conforming extension that should trigger a warning when using the -pedantic flag similar in vain to issue in Is it a conforming compiler extension to treat non-constexpr standard library functions as constexpr?.

C ++ 11/C ++ 14报价

5.20节是C ++ 14和C ++ 11中的5.19节,来自C ++ 14标准草案的相关引用是:

Section 5.20 is section 5.19 in C++14 and C++11, the relevant quote from the draft C++14 standard is:

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

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

  • 整数或枚举类型的非易失性glvalue,它引用具有以下内容的非易失性const对象: 先前的初始化,使用常量表达式初始化[注意:字符串文字(2.14.5) 对应于此类对象的数组. —尾注]或

  • a non-volatile glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression [ Note: a string literal (2.14.5) corresponds to an array of such objects. —end note ], or

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

a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable sub-object of such an object, or

文字类型的非易失性glvalue,指的是其生命周期开始的非易失性对象 在e的评估之内;

a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

,对于C ++ 11标准草案是:

and for the draft C++11 standard is:

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

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

  • 整数或枚举类型的glvalue,它引用具有前面的非易失性const对象 初始化,使用常量表达式初始化,或者

  • a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or

文字类型的glvalue引用使用constexpr定义的非易失性对象,或引用 到此类对象的子对象,或

a glvalue of literal type that refers to a non-volatile object defined with constexpr, or that refers to a sub-object of such an object, or

字面量类型的glvalue指的是其生存期未达到的非易失性临时对象 结束,使用常量表达式初始化;

a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not ended, initialized with a constant expression;

这篇关于int a = 1,是|| 1个常量表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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