c++新特性实验(3)声明与定义:constexpr

1.作用

  constexpr 声明一个函数或变量,它的值可以在编译时出现在常量表达式之中。

2.constexpr 变量要求

  • 其类型必须是 字面类型 (LiteralType) 。
  • 它必须被立即初始化
  • 其初始化的全表达式,包括所有隐式转换、构造函数调用等,都必须是常量表达式.

3.constexpr 普通函数要求

  • 必须非虚.(C++20 前)
  • 返回类型必须是字面类型 (LiteralType)
  • 其每个参数都必须是字面类型 (LiteralType)
  • 至少存在一组实参值。
  • 函数体必须不含 (C++14 后)
    1. asm 声明
    2. goto 语句
    3. 拥有除 case 和 default 之外的标号的语句
    4. try 块 (C++20 前)
    5. 非字面类型的变量定义
    6. 静态或线程存储期变量的定义
    7. 不进行初始化的变量定义。
=default; 或 =delete; 的函数体不含任何上述内容。)
  • 函数体必须被弃置或预置,或只含有下列内容:(C++14 前)
    1. 空语句(仅分号)
    2. static_assert 声明
    3. 不定义类或枚举的 typedef 声明及别名声明
    4. using 声明
    5. using 指令
    6. 恰好一条 return 语句。

4.constexpr构造函数的要求

  • 其每个参数都必须是字面类型 (LiteralType) 
  • 不能有虚继承
  • 该构造函数必须无函数 try 块
  • 构造函数体必须满足 constexpr 函数体的制约
  • 对于 class 或 struct 的构造函数,每个子对象和每个非变体非 static 数据成员必须被初始化。若类是联合体式的类,对于其每个非空匿名联合体成员,必须恰好有一个变体成员被初始化
  • 对于非空 union 的构造函数,恰好有一个非静态数据成员被初始化
  • 每个被选用于初始化非静态成员和基类的构造函数必须是 constexpr 构造函数。
  • 构造函数体必须被弃置或预置,或只含有下列内容:
    1. 空语句
    2. static_assert 声明
    3. 不定义类或枚举的 typedef 声明及别名声明
    4. using 声明
    5. 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 }

 

posted @ 2019-04-15 22:39  f9q  阅读(742)  评论(0编辑  收藏  举报