1.常量表达式
1.1.引入背景
#include <iostream>
const int GetConst(){return 1;}
void Constless(int cond){
//int arr[GetConst()] = {0};//err
//enum{e1 = GetConst(), e2};//err
switch(cond){
//case GetConst()://err
break;
default:
break;
}
}
上述三处均无法使用GetConst(),因为const修饰的变量是运行期变量。
上述三处需要编译期常量。通过枚举,#define,字面常量可以得到编译期常量。
1.2.c++11引入constexpr
(1). 通过constexpr得到返回值是编译期常量的函数。
#include <iostream>
constexpr int GetConst(){return 1;}
void Constless(int cond){
int arr[GetConst()] = {0};//ok
enum{e1 = GetConst(), e2};//ok
switch(cond){
case GetConst()://ok
break;
default:
break;
}
}
使用constexpr修饰函数返回值时,对函数的要求:
a. 函数体只能包含单个语句,这个语句必须是return。
b. 函数必须有返回值(void不算)。
c. 当在编译期通过函数调用取得编译期常量处,函数定义需可见。
d. return中的表达式需要是常量表达式。(当一个表达式的所有参与成员均是常量表达式时这个表达式整体是常量表达式)。
(2).如何判断单个成员构成常量表达式:
单个成员是enum值,#define值,字面常量,constexpr修饰的变量时。
用constexpr修饰的变量必须使用常量表达式执行初始化。
(3).如何才能将自定义类型变量添加constexpr修饰
#include <iostream>
struct MyType{
constexpr MyType(int x):i(x){}
constexpr GetInt(){return i;}// 一个constexpr修饰的类型,其字段依然有constexpr性质。
int i;
};
constexpr MyType mt = {0};
int main(){
return 0;
}
需要为类型的构造函数添加constexpr修饰。
添加constexpr修饰的构造需满足:
a.函数体为空
b.接收的实参列表中每个实参需为常量表达式
(4). 模板推导下特殊处理说明
#include <iostream>
struct NotLiteral{
NotLiteral(){i=5;}
int i;
};
NotLiteral n1;
template<typename T>
constexpr T ConstExp(T t){
return t;
}
void g(){
NotLiteral n1;
NotLiteral nl1 = ConstExp(n1);
//constexpr NotLiteral n12 = ConstExp(n1);// err
constexpr int a = ConstExp(1);
}
int main(){
return 0;
}
上述模板函数ConstExp,预期返回值是常量表达式。
如果上述是一个非模板函数,则要求实参必须是常量表达式。
针对上述模板函数,做了特别处理:
实参是常量表达式时,返回值自然是常量表达式。
实参不是常量表达式时,不报错,返回值是非常量表达式。