《C++ Templates》略读
https://github.com/Walton1128/CPP-Templates-2nd–
C++ 11、14 和 17 中的新特性
这一部分列出来了需要学习的新特性
C++ 11 引入了非常多的特性:
- 变参模板(Variadic templates)
- 模板别名(Alias templates)
- 移动语义(Move semantics)、右值引用(RValue references)和完美转发(Perfect forwarding),这三个需要之后去着重看一下
- 标准类型萃取(Standard type traits)
C++ 14 与 C++ 17 也引入了一些新的特性,但没有 C++ 11 那么多:
- 变量模板(Variable templates,C++ 14)
- 泛型 lambda(Generic Lambdas,C++ 14)
- 类模板参数推断(Class template argument deduction,C++ 17)
- 折叠表达式(Fold expression,C++ 17)
C++ 20 中,引入了:
- 模板接口(Concept)
函数模板初探
两阶段编译检查(Two-Phase Translation)
在编译阶段,模板并不是被编译成一个实体,而是对于每一个使用该模板的类型都生成实体
生成实体的过程被称作实例化
类型可以被推断为 void
两阶段编译检查:
- 模板定义阶段:检查语法(如少不少分号);检查是否有未定义的名称(如模板参数中没有
T
却使用了它);检查不依赖于模板参数的静态断言(此时没有装填具体的类型进去,只能进行这种断言的检查) - 模板实例化阶段:检查其他东西,尤其是依赖于模板参数的部分
类型推断
类型推断中的类型转换有限制:
- 引用传递的参数不能进行任何类型的类型转换
- 按值传递只允许进行退化(decay):如忽略
const
和volatile
、去掉引用、数组和函数转换为指针
缺省参数不参与类型推断,如:
template <typename T>
void f(T value = "") {}
f(); // 报错,因为无法推断 T 的类型
template <typename T = std::string>
void f(T value = "") {}
f(); // 正常
多个模板参数
当使用了多个模板参数后,这么写的话,返回值的类型可能会与传参顺序有关:
template<typename T1, typename T2>
T1 max(T1 a, T2 b) { ... }
auto m1 = max(4, 7.2); // 返回 int
auto m2 = max(7.2, 4); // 返回 double
为了避免这种情况,有三种方法:
第一种是引入第三个模板参数作为返回类型:
template<typename RT, typename T1, typename T2>
RT max (T1 a, T2 b);
max<double>(4, 7.2);