c++新特性实验(3)声明与定义:constexpr
1.作用
constexpr
声明一个函数或变量,它的值可以在编译时出现在常量表达式之中。
2.constexpr 变量要求
- 其类型必须是 字面类型 (LiteralType) 。
- 它必须被立即初始化
- 其初始化的全表达式,包括所有隐式转换、构造函数调用等,都必须是常量表达式.
3.constexpr 普通函数要求
-
- 必须非虚.(C++20 前)
- 返回类型必须是字面类型 (LiteralType)
- 其每个参数都必须是字面类型 (LiteralType)
- 至少存在一组实参值。
- 函数体必须不含 (C++14 后)
- asm 声明
- goto 语句
- 拥有除
case
和default
之外的标号的语句 - try 块 (C++20 前)
- 非字面类型的变量定义
- 静态或线程存储期变量的定义
- 不进行初始化的变量定义。
- (=default; 或 =delete; 的函数体不含任何上述内容。)
- 函数体必须被弃置或预置,或只含有下列内容:(C++14 前)
- 空语句(仅分号)
- static_assert 声明
- 不定义类或枚举的 typedef 声明及别名声明
- using 声明
- using 指令
- 恰好一条 return 语句。
4.constexpr构造函数的要求
- 其每个参数都必须是字面类型 (LiteralType)
- 不能有虚继承
- 该构造函数必须无函数 try 块
- 构造函数体必须满足 constexpr 函数体的制约
- 对于 class 或 struct 的构造函数,每个子对象和每个非变体非 static 数据成员必须被初始化。若类是联合体式的类,对于其每个非空匿名联合体成员,必须恰好有一个变体成员被初始化
- 对于非空 union 的构造函数,恰好有一个非静态数据成员被初始化
- 每个被选用于初始化非静态成员和基类的构造函数必须是 constexpr 构造函数。
- 构造函数体必须被弃置或预置,或只含有下列内容:
- 空语句
- static_assert 声明
- 不定义类或枚举的 typedef 声明及别名声明
- using 声明
- using 指令
5.constexpr if
- 以
if constexpr
开始的语句被称为constexpr if 语句。 - 在 constexpr if (条件)语句中,条件的值必须是可转换到
bool
类型的常量表达式。 - 若其值为
true
,则抛弃 false分支语句(若存在),否则抛弃true分支语句。
6.示例
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstdint> 4 #include <vector> 5 6 static void 7 fun(){ 8 //printf("%s called \n",__func__); 9 } 10 11 constexpr int 12 getCount(){ 13 int a = 4; 14 int b = 4; 15 a *= b; 16 //printf("%s called \n",__func__); //error,C++11 constexpr 函数必须把一切放在单条 return 语句中,C++14 无此要求 17 //fun(); //error,fun 不是constexpr 18 return 4 * 4; 19 } 20 21 class person{ 22 protected: 23 virtual void getName(); 24 }; 25 26 class student : /*virtual*/ public person{ // 不能有虚继承 27 private: 28 constexpr static int LEN = 32; 29 char16_t name[getCount()]; //getCount() 是constexpr函数。 30 uint8_t age; 31 public: 32 constexpr student():name(u"hello"),age(getCount()){ 33 typedef int INT; 34 using namespace std; 35 enum Color{ 36 Red,Green,Blue, 37 }; 38 Color color = (Color)0; 39 } 40 student(int ){ 41 } 42 /* 43 virtual constexpr int getAge(){ //error,constexpr成员函数不能是virtual的。 44 return 100; 45 } 46 */ 47 virtual void getName(){ 48 49 } 50 friend constexpr char16_t* getName(student &,int max = 100); 51 }; 52 53 constexpr char16_t* 54 getName(student &s,int max){ 55 using namespace std; 56 typedef class student Student; 57 //static int value = 100; //error,不能有静态变量。 58 //vector<int> vec; //error,不是常量表达式。 59 if(s.age < 0){ 60 //goto END; //error,不能有goto 61 } 62 63 //__asm__("movl %eax, %ebx\n\t"); //error,不能有汇编语句。 64 65 /* 66 try{ //error,不能有try...catch语句。 67 ++s.age; 68 }catch(const exception &e){ 69 printf("exception \n"); 70 } 71 */ 72 73 switch(s.age){ 74 case 1 : return u"ek"; /* U"0" */; // U是char32_t,u是char16_t 75 case 2 : return u"fel"; 76 default : return u"Default"; 77 } 78 END: 79 return u"error"; 80 } 81 82 83 int 84 main(int argc,char *argv[]){ 85 86 if constexpr(getCount() > 0){ 87 #line 1024 "test.cpp" 88 } 89 printf("file = %s,line = %d\n",__FILE__,__LINE__); 90 return 0; 91 }