Constant expressions
常数表达式
定义表达可以在编译时进行评估。
这类表达式可以用作非类型模板参数、数组大小,以及在需要常量表达式的其他上下文中使用,例如,
二次
int n = 1;
std::array<int, n> a1; // error, n is not a constant expression
const int cn = 2;
std::array<int, cn> a2; // OK, cn is a constant expression
二次
核心常数表达式
阿核心常数表达式
是指不
在任何子表达式%28中有下列任何一个忽略未计算的表达式,例如sizeof
或内建的右操作数。&&
当左操作数计算为false
29%。
1%29调用函数表达式,调用函数%28或未声明的构造函数%29司法官
二次
constexpr int n = std::numeric_limits<int>::max( // OK, max() is constexpr
constexpr int m = std::time(NULL // Error: std::time() is not constexpr
二次
2%29 a函数调用constexpr
函数,该函数声明但未定义,或调用constexpr
函数/构造函数模板实例化,其中实例化不能满足常数函数/构造函数要求。
3%29 a函数调用constexpr
函数的参数,这些参数在替换时不会产生常量表达式。
二次
constexpr const int* addr(const int& ir) { return &ir; }
static const int x = 5;
constexpr const int* xp = addr(x // OK
constexpr const int* tp = addr(5 // error: &5 is not a constant expression
二次
4%29 a函数调用constexpr
构造函数,其参数在此函数调用的成员初始化程序列表中不生成常量表达式。
二次
int x;
struct A {
constexpr A(bool b) : m(b?42:x) { }
int m;
};
constexpr int v = A(true).m; // OK
constexpr int w = A(false).m; // error: non-const x
二次
5) A function call to a recursive constexpr function that would exceed compile-time recursion depth limit (implementation-defined) | (until C++14) |
---|---|
5) an expression that would exceed the implementation-defined limits | (since C++14) |
6) The this pointer, except if used for class member access inside a non-static member function | (until C++14) |
---|---|
6) The this pointer, except in a constexpr function or a constexpr constructor that is being evaluated as part of the expression | (since C++14) |
7%29一个表达式,其计算结果导致任何形式的核心语言未定义行为%28,包括有符号整数溢出、除以零、指针算法在数组边界外等等。是否检测到标准库未定义的行为未指定。
二次
constexpr double d1 = 2.0/1.0; // OK
constexpr double d2 = 2.0/0.0; // Error: not defined
constexpr int n = std::numeric_limits<int>::max() + 1; // Error: overflow
int x, y, z[30];
constexpr auto e1 = &y - &x; // Error: undefined
constexpr auto e2 = &z[20] - &z[3]; // OK
constexpr std::bitset<2> a;
constexpr bool b = a[2]; // UB, but unspecified if detected
二次
8) A lambda expression | (until C++17) |
---|
9%29英镑隐式转换或修改%28,因为C++14%29应用于联合或者它的子物体
10%29任何其他的价值对价值隐式转换,除非那个...
%29具有整数或枚举类型,并引用完全非易失性Const对象,该对象使用常量表达式初始化。
二次
int main() {
const std::size_t tabsize = 50;
int tab[tabsize]; // OK: tabsize is a constant expression
std::size_t n = 50;
const std::size_t sz = n;
int tab2[sz]; // error: sz is not a constant expression
// because sz is not initialized with a constant expression
}
二次
B%29是一个非易失性的glvalue,它引用字符串文字的一个元素。
C%29具有文字类型,并引用一个非易失性对象,该对象由constexpr
或者它不可变的子对象。
d) has literal type and refers to a non-volatile temporary object, initialized with a constant expression | (until C++14) |
---|---|
d) has literal type and refers to a non-volatile object whose lifetime began within the evaluation of this expression | (since C++14) |
11%29引用类型的变量或数据成员的id表达式.。除非它是用常量表达式初始化的,或者是临时对象的非静态数据成员,而临时对象是用常量表达式%28初始化的,直到C++14%29为止,否则它的生存期将在计算此表达式%28时开始,因为C++14%29。
12) conversion from cv void* to any pointer-to-object type | (since C++14) |
---|
13%29动态[医]铸造
14%29重释[医]铸造
15%29伪析构函数调用
16) an increment or a decrement operator | (until C++14) |
---|---|
16) modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression constexpr int incr(int& n) { return ++n; } constexpr int g(int k) { constexpr int x = incr(k // error: incr(k) is not a core constant // expression because lifetime of k // began outside the expression incr(k) return x; } constexpr int h(int k) { int x = incr(k // OK: x is not required to be initialized with a core // constant expression return x; } constexpr int y = h(1 // OK: initializes y with the value 2 // h(1) is a core constant expression because // the lifetime of k begins inside the expression h(1) | (since C++14) |
17%29 a类型应用于多态类型的极值的表达式
18%29新表达式或删除表达式
19%29当结果未指定时,等于运算符或关系运算符。
20) an assignment or a compound assignment operator | (until C++14) |
---|
21%29次抛出表达式
22%29在lambda表达式中,引用this
如果引用是ODR-Use,也可以定义在该lambda之外的变量。
二次
void g() {
const int n=0;
constexpr int j=*&n; // OK, outside of a lambda-expression
[=]{ constexpr int i=n; // OK, 'n' is not odr-used and not captured here.
constexpr int j=*&n;// Ill-formed, '&n' would be an odr-use of 'n'.
};
}
二次
note that if the ODR-use takes place in a function call to a closure, it does not refer to this or to an enclosing variable, since it accesses a closure's data member instead. // OK: 'v' & 'm' are odr-used but do not occur in a constant-expression // within the nested lambda auto monad = {return ={return v;};}; auto bind = {return ={return fvm(m()};}; // OK to have captures to automatic objects created during constant expression evaluation. static_assert(bind(monad(2))(monad)() == monad(2)() | (since C++17) |
---|
积分常数表达式
积分常数表达式
一个整数或非作用域枚举类型的表达式,隐式转换为prvalue,其中转换的表达式是核心常量表达式。如果使用类类型的表达式(其中需要一个积分常量表达式),则表达式为上下文隐式转换到整数或非作用域枚举类型。只有积分常量表达式可以用作。
阵列界的维度新表达式除了第一个%28到C++14%29,位场长度,当基础类型不固定时,枚举初始化器,空指针常数%28,直到C++14%29,以及对齐。
转换常数表达式
阿转换常数表达式
类型T
是一个表达式隐式转换若要键入T
,则转换表达式为常量表达式,而隐式转换序列仅包含:
- 用户定义的转换%28,因此可以在期望积分类型为%29的情况下使用类。
- lvalue-rvalue转换
- 整体晋升
- 非窄积分变换
array-to-pointer conversions function-to-pointer conversions function pointer conversions (pointer to noexcept function to pointer to function) qualification conversions null pointer conversions from std::nullptr_t null member pointer conversions from std::nullptr_t | (since C++17) |
---|
- 数组到指针转换
- 函数指针转换
- 函数指针将%28指针转换为no,但函数指针转换为函数%29
- 资格转换
- 空指针转换
std::nullptr_t
- 的空成员指针转换
std::nullptr_t
%28自C++17%29
- 如果有的话参考绑定发生时,直接绑定%28而不是构造临时对象%29。只
转换常数表达式
可用作案例表达式,,,枚举数初始化器当基础类型固定时,阵列界的维度新表达式除第一%28自C++14%29外,并为整数和枚举%28,直到C++17%29非类型。模板参数...阿类型的上下文转换常量表达式
bool
是一种表达,上下文转换为bool
,其中转换的表达式是常量表达式,而转换序列仅包含上面的转换。这些表达式可用于noexcept
规格和静态断言声明...文字常量表达式
文字常量表达式
是一个prvalue核心常数表达式
非指针文字类型%28的转换后,根据上下文%29的要求。数组或类类型的文字常量表达式
要求每个子对象都用一个常量表达式初始化。参考常数表达式
参考常数表达式
是一个lvalue核心常量表达式,它指定具有静态存储持续时间或函数的对象。地址常量表达式
地址常量表达式
是类型的上下文%29所要求的转换后的prvalue核心常量表达式%28。std::nullptr_t
或指向具有静态存储持续时间的对象的指针类型,或指向具有静态存储持续时间的数组结束后的对象,指向函数,或为空指针。注记实现不允许将库函数声明为conexpr,除非标准说明该函数在常量表达式中是强制性的。%28自C++14%29缺陷报告以下行为更改缺陷报告追溯应用于先前发布的C++标准。博士适用于公布的行为正确行为CWG 2167C++14评估的非成员引用(局部为评估)使评估成为非成员引用。允许非会员引用CWG 1313C++11允许未定义的行为,并禁止所有指针减法。相同数组指针减法确定,UB禁止。CWG 1952C++11标准库中未定义的行为需要进行诊断。未指定库UB是否被诊断另见
- 常数说明符
std::is_literal_type
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。