N4527 5.20【expr.const】p5
常量表达式是glvalue核心常量表达式,其值是指常量表达式(定义如下)的允许结果实体,或者是prvalue核心常量表达式,其值是对象,其中,对于该对象及其子对象:
-引用类型的每个非静态数据成员引用一个实体,该实体是常量表达式的允许结果,并且
-如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址、超过此类对象结尾的地址(5.7)、函数的地址或空指针值。
如果实体是具有静态存储持续时间的对象,而该对象不是临时对象,或者是值满足上述约束的临时对象,或者是函数,则实体是常量表达式的允许结果。
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
;
}
}
是一个常量表达式吗?
N4527 5.20[膨胀常数]p2
条件表达式e是一个核心常量表达式,除非根据抽象机器(1.9)的规则对e求值将求值以下表达式之一:
(2.7)-左值-右值转换(4.1),除非它应用于
(2.7.1)-整数或枚举类型的非易失性glvalue,指的是具有先前初始化、使用常量表达式初始化的完整非易失性常量对象,或
(2.7.2)-非易失性glvalue,它引用字符串文字(2.13.5)的子对象,或
(2.7.3)-一个非易失性glvalue,它指的是一个非易失性对象,或者指的是这样一个对象的一个不可变的子对象,或者
(2.7.4)-文字类型的非易失性glvalue,指的是寿命开始于e评估范围内的非易失性对象;
是核心常量表达式吗?
如果编译器检查整个赋值链,那么它可以确定“a||1”是一个常量表达式。但是,由于a是一个变量,除非编译器检查a没有被赋值,否则它无法知道“a||1”是一个常量表达式。
重复您的报价:
(2.7)-左值-右值转换(4.1),除非它应用于
(2.7.1)-整数或枚举类型的非易失性glvalue,指的是具有先前初始化、使用常量表达式初始化的完整非易失性常量对象,或
a
涉及左值-右值转换。由于a
不是const对象,这意味着a
不是核心常量表达式;因此a||1
也不是。
但是,如果您的代码是:
const int a = 1;
那么a | | 1将是一个核心常量表达式。
<代码>a 不是常量表达式(请参见下面的标准引号),因此:
a || 1
也不是一个常量表达式,虽然我们知道表达式必须求值为true,但这里的标准要求从左到右求值,我看不到允许编译器跳过a的左值到右值转换的例外。
但是:
const int a = 1;
可以在常量表达式中使用,因为它属于5.20p2的异常(emphasis mine):
左值到右值的转换(4.1),除非应用于
这条规则也是为什么原始case不是常量表达式的原因,因为没有一个异常适用。
也许gcc允许这样做:
int b[a || 1]{};
作为可变长度数组的扩展,尽管它应该使用pedantic提供警告。虽然这不能解释static\u assert的情况,但它们可以是常量折叠它,但我认为“好像”规则不允许将其视为常量表达式
更新,可能的gcc扩展
根据此错误报告,逻辑运算符的RHS可能会使LHS在常量表达式中未赋值,这看起来像是一个可能的gcc扩展:
尽管在常量表达式中使用了非常量对象,但编译时不会发生意外:
int i;
static_assert( i || true, "" );
static_assert( ! ( i && false ), "" );
似乎是假设| |和
最后的评论是:
我认为这是一个有目的的语言扩展,可以使用开关禁用。如果static\u断言总是严格的,那就太好了。
这似乎是一个不一致的扩展,当使用pedantic标志时,它会触发一个警告,类似于在将非constexpr标准库函数视为constexpr?中发出的一致性编译器扩展?。
C 11/C 14报价
第5.20节是C 14和C 11中的第5.19节,C 14标准草案中的相关引用是:
左值到右值的转换(4.1),除非应用于
>
整数或枚举类型的非易失性glvalue,它引用具有先前初始化的非易失性const对象,使用常量表达式初始化[注意:字符串文字(2.14.5)对应于此类对象的数组。-结束注释],或
一个非易失性glvalue,它指的是一个非易失性对象,或者指的是这样一个对象的一个不可变的子对象,或者
一个文本类型的非易失性glvalue,它指的是一个非易失性对象,其生存期开始于对e的求值;
对于C 11草案,标准为:
左值到右值的转换(4.1),除非应用于
>
一个文字类型的glvalue,它引用了一个非易失性对象,或者引用了这样一个对象的子对象,或者
文字类型的glvalue,指的是生命周期尚未结束的非易失性临时对象,用常量表达式初始化;
问题内容: 我需要寻找java regex模式,该模式以1 = 1的格式查找输入字符串,其中前缀“ =”应具有与后缀相同的位数。同样,这里的前缀和后缀值应相同,例如1 = 1、11 = 11、223 = 223。像1 = 2、3 = 22、33 = 22之类的值不应与模式匹配 我们能否有一个满足上述规则的一般模式。 问题答案: 使用反向引用: 当然,在Java中,您需要转义反斜杠:
问题内容: 以下在我的Eclipse中可以正常编译: Java甚至一开始就阻止了许多“愚蠢的代码”的编译(例如,没有编译!),所以它甚至没有产生像警告一样多的事实,这令我感到非常惊讶。当您考虑允许在编译时优化常量表达式这一事实时,这种兴趣就加深了: 上面的代码段在Eclipse中编译,生成了以下字节码() 如您所见,和分配被优化为编译时常量,但是除法(必须在编译时可检测到)被简单地按原样编译。 它
常量表达式机制是为了: 提供一种更加通用的常量表达式 允许用户自定义的类型成为常量表达式 提供了一种保证在编译期完成初始化的方法(可以在编译时期执行某些函数调用) 考虑下面这段代码: enum Flags { good=0, fail=1, bad=2, eof=4 }; constexpr int operator|(Flags f1, Flags f2) { return Flags(int(
序:世界上信息非常多,而我们关注的信息有限。假如我们希望只提取出关注的数据,此时可以通过一些表达式进行提取,正则表达式就是其中一种进行数据筛选的表达式。 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。 正则表达式通常被用来匹配、检索、替换和分割那些符合某个模式(规则)的文本。 Python 自1.5版本起
为什么 -1 是 true
问题内容: 我在switch / case语句中遇到问题。该错误显示:“ case表达式必须是常量表达式”。我理解该错误,可以使用If来解决它,但是有人可以告诉我为什么case表达式在switch / case中必须是常量。我的错误的代码示例: 谢谢你的解释!! 问题答案: 因此可以在编译阶段进行评估(静态检查) 请参阅:http://docs.oracle.com/javase/specs/jl