本文内容绝大部分出自:cppreference
1概念:
常量,是在编译期间就可以求得值的量,常量通常可以作为数组长度,模板非类型参数等
核心常量表达式,核心常量是一个无意义的规定性概念,概念内容是:只要不存在对某些特定的表达式求值,那么这个表达式就是核心常量表达式.
字面类型:
字面类型是标准之外的一个用于统一说法的一个定义:
字面类型包括:
可有cv限定的void
标量类型
引用类型
字面类型的数组
可有cv限定的类类型,并且包含:
平凡析构
聚类或含有constexpr构造或为闭包类型
对于class而言:
对于联合体,那么至少有一个非静态数据成员是volatile字面类型
对于非联合体,所有非静数据成员和基类是非volatile的
其中,字面类型是constexpr所拥有的类型,只能通过constexpr函数操作和返回.
核心常量表达式:
(批注:始于表达式之内的例子,最好证明的就是发生在函数调用,实参是一个核心常量,形参则始于表达式之内)
除了存在表达式对以下项求值之外的表达式都是核心常量表达式:
1:除了constexpr的类成员函数(包括构造函数)内使用的this,其余对this(间接)求值的表达式均不是核心常量表达式
2:调用不为constexpr的函数(包括构造函数)的函数调用表达式
3:调用了声明为constexpr,但是无定义的
4:调用constexpr模板函数,但是模板实例化后无法满足constexpr函数要求的
5:对于不同实现的特殊要求,如果存在超出的情况的表达式
6:一个constexpr表达式,但是可以导致未定义行为的(溢出,越界,悬空指针)
7:Lambda
8:左值到右值的隐式转换,除非这个左值有以下性质:
拥有整数或枚举类型,并且指代完整的非volite的const对象,并且该对象以核心常量表达式初始化
指代字符串字面量元素的非volatile泛左值
拥有字面类型,并指代以constexpr定义的非volite对象,或模板参数对象
拥有字面类型,并指代生存期始于此表达式的求值内的非volate对象
9:指代引用类型变量,或数据成员的id,除非该引用以常量表达式初始化,或生存期始于该表达式求值
10:从(cv)void*转为任何类型的表达式
11:dynamic_cast,reinterpret_cast
12:伪析构调用
13:自增自减(新版本为14,在C++14前生效)
14:对象的修改,除非对象是非volatile字面类型,并且是始于该表达式求值内的
15:typeid,对象为多态
16:new,delete
17:throw
18:结果未指定时的关系运算
19:赋值,复合赋值(C++14前)
20:三路比较(C++20)
整形常量表达式
即满足上述左值转为纯右值的要求的整数或无作用域枚举<即:非voliate的const或枚举,经过核心常量表达式初始化的,指代字面量元素的非voliate的泛左值或constexpr定义的非voliate对象,或模板参数对象,生存期始于当前表达式求值的非,voliate对象>如果是类类型表达式,则服从于对象的隐式转换,转换为整数,无作用域枚举.
经转换的整形常量表达式
即通过转换到类型T的表达式,其中转换后的表达式是常量表达式,并且隐式转换的序列有:
constexpr用户定义转换
左值到右值(满足上述规则)
整数类型提升
非窄化整数转换
常量表达式
常量表达式通常指代:
在泛左值中:
有静态存储期,并且非零时对象
函数
静态存储期的零时对象,值满足下列纯右值制约
在纯右值中:
类类型对象,其中每个引用类型的非静态数据成员指代满足上述对泛左值制约的实体
若值是类类型对象,则其每个引用类型的非静态数据成员指代满足上述对泛左值制约的实体
若值有指针类型,则它保有
拥有静态存储期的对象地址
拥有静态存储期的对象的结尾后一位置地址
函数地址
空指针值
若值拥有类或数组类型,则每个子对象满足这些对值的制约
满足以上者,为常量表达式.