模版元编程、自动类型推导 与 函数式编程
关于模版元编程和函数式编程,涉及到的是C++的5种编程范式,i.e.
- 面向过程
- 面向对象
- 函数式
- 范型
- 模版元编程
模版元编程
元编程(metaprogramming)是指编写能够生成或操作其他程序的程序。
- 写在尖括号内的包含两种内容:模版类型参数和非模版类型参数
- 可以为模版类型参数指定默认值
- 非模版类型参数同普通函数相比,前者是编译时常量,后者是运行时常量,编译器可以对前者在编译时进行优化(可通过
constexpr
指定某一变量是编译时常量) - 可定义多个模版参数
- 除非使用特殊手段,否则应将模版的声明和定义放置在一起,无法使用头文件函数声明和cpp文件函数定义分离的方式,问题在于会使二进制文件大小过大
调用函数模版,编译器推断模版参数类型的过程称为模版实例化,编译器在面对函数模版的定义时,是不生成代码的,只有当模版实例化时,才会真正生成代码,此性质称为延迟编译(不过在mac上的实际表现并非如此,可能和mac的编译器有关)
函数模版的原理是在编译时生成多份函数,编译器根据实例化代码生成对应类型的函数
模版的困难点在于编译期常量的限制,即所有涉及到模版参数的参数都必须是编译期常量,可通过constexpr关键字显示指定使得某些运行时常量变为编译时常量。
需要注意模版参数使用class
和typename
的区别
自动类型推导auto
使用要求:
- 声明变量的同时必须进行赋值,否则类型无法推导
- 类成员变量不允许声明为auto
万能推导decltype(auto)
函数式编程
注意和函数指针进行区分,函数指针示例如下
#include <iostream>
void func() {
std::cout << "call func()" << std::endl;
}
int main() {
void (*p)() = func;
p(); // output: call func()
return 0;
}
- 函数作为函数参数,作为返回值(如果为了声明和定义分离提高编译速度而不能使用auto,可以采用std::function)
- lambda表达式
- 变量捕获:如果不进行变量捕获,则使用[],那么lambda函数体内是无法使用处于lambda参数列表之外且定义于lambda位置的其他变量。使用[&]实现lambda捕获定义它的位置中的变量,同时这一特性称为闭包(closure)。变量捕获需要保证lambda的生命周期要不超过引用变量的生命周期,即lambda存在时引用必须存在。为了解决这一问题,可以采用[=],即不采用引用,而是直接将数据进行拷贝