1. 函数模板
1.1 模板参数
模板参数的确定顺序:
- 显式指定
- 隐式推导 & 标记协定(comparing notes)
- 默认类型
1.1.1 模板类型推导
Reference collapsing [Doc]
& + & = &
& + && = &
&& + & = &
&& + && = &&
1.2 函数模板特化
特化示例:template void fun(int) / template void fun(int)
Note
template
关键字不能省略。
可以使用函数重载可以代替函数模板的完全特化
示例:Cpp_overload_specialization
使用相同形式的函数重载可以在某些情况下替代函数模板的完全特化。具体来说,如果函数模板的模板参数推导过程不会产生任何歧义,并且模板参数的类型和重载函数的参数类型完全匹配,那么编译器会优先选择重载函数,而不是实例化函数模板。
2. 类模板
2.2 偏特化有点类似于“模板式的函数重载”
3. Q&A
(1)C++中的模板和宏展开本质上是相同的吗?
不是。C++中的模板和宏展开是不同的两种实现机制。模板是在编译时进行代码生成,并在类型确定时编译;而宏展开是在预处理时进行代码替换,而不进行类型检查。
(2)C++的STL库的实现有使用到“类模板特化”吗?
是的,C++的STL库使用了类模板特化的技术。例如,STL的vector模板类在特化std::vector时,实现了特殊的内存布局和比特级操作。此外,STL的其他组件,如std::pair,std::tuple等也使用了类模板特化技术,以支持更多的数据类型(OCP原则的应用)。
4. Notes
C++17之前(by C++11)不支持类模板的类型推导:引入辅助模板函数
例如,make_pair
就是一个典型的辅助模板函数,
#include <iostream>
#include <utility>
template <typename T1, typename T2>
std::pair<T1, T2> make_pair(T1 vall, T2 val2){
return std::pair<T1, T2>(vall, val2);}
int main() {
auto x = make_pair(3,3.14);
}
5. Defect records
5.1 不能将带有变长参数的模板使用符号整体表示
示例代码:Cpp_var_template
// 缺陷写法:
template<Cont<unsigned int...> RA, Cont<unsigned int...> Cont RB>
struct Add<RA, RB> {
// 想使用<RA, RB>直接表示数组,不过无法通过编译
using A = typename ReverseCont<RA>::type;
using B = typename ReverseCont<RB>::type;
using result = typename Add<A, B, Cont<>>::type;
using cont = typename ReverseCont<result>::type;
};
这种代码是不允许的,不过使用一个符号整体表示一个带有变长参数的模板;