chapter 13.pdf
函数模板

声明:不带大括号,可以多次声明
定义:带大括号,只能定义一次
template<typename T> void fun(T); //声明,可用class代替typenametemplate<typename T> void fun(T) //定义{}template<typename T> void fun(T input){cout<<input<<endl;}template //表示模板函数T //模板形参,如果在编译期能够得到模板实参,则可在编译期实例化为实体函数input //函数形参,运行期调用
函数模板显示实例化
fun<int>(3) //函数模板显式实例化,函数模板非函数不能调用,但是实例化后产生的函数为函数,可调用int //对应T,模板实参3 //对应input,函数实参
编译期的两阶段处理
模板语法检查:
模板实例化:获取模板实参后,根据模板实参检查操作是否合法
模板必须在实例化的时候可见:整个程序可以多处定义,只要符合翻译单元处一处定义原则即可
与inline的区别:inline函数是在翻译单元中展开代码
类型推导

template<typename T> void fun(T input) //定义{}int main(){fun(3); //隐式实例化,类型推导模板实参}
实例化控制
显式实例化定义
//main.cpp#include "header.h"int main(){int x = 3;fun<int>(x);}
//header.h#include<iostream>template<typename T>void fun(T x){cout<<x<<endl;}//可以将定义与声明分开,只开放定义接口给用户templatevoid fun<int>(int x); //显式实例化void fun(int x); //同上,显式实例化
显示实例化声明
避免多个相同实例化,提高编译连接速度
//main.cpp#include <iostream>#include "header.h"extern template <typename T>//c++11,显式实例化声明void fun(int x);int main(){int x = 3;fun<int>(x);}
//source.cpp#include "head.h"templatevoid fun(int x)
//header.h#include <iostream>template<typename T>void fun(T x){cout<<x<<endl;}
模板形参推导
//main.cpp#include <iostream>template <typename T>void fun(T x){cout<< x <<endl;}templatevoid fun(int* x); //实例化为第一个模板函数,template <typename T>void fun(T* x){cout<< x <<endl;}templatevoid fun(int* x); //实例化为第二个模板函数,形参推导为离当前实例化近的定义templatevoid fun<int*>(int* x); //实例化为第一个模板函数,因为int*和参数列表的int*一致,T = int*int main(){}
函数模板的特化
#include<iostream>template<typename T>void fun(T x){cout<<x<<endl;}//可以将定义与声明分开,只开放定义接口给用户templatevoid fun<int>(int x); //显式实例化void fun(int x); //同上,显式实例化//函数模板特化,为某些模板参数引入特殊的实现,下面带大括号,实例化无大括号template<> void fun<int>(int x){}
类模板与成员函数模板
声明与定义
template <typename T>class B{public:void fun(T input)//类内定义{cout<<input<<endl;}};//定义template <typename T>void B<T>::fun() //类外定义成员函数{}template<typename T>class B; //声明struct Str{};int main(){B<int>x; //实例化x.fun(3); //成员函数此时被实例化B<Str> y; //y.fun(Str{}) //错误:Str没有对应<<重载,但是上一句可以编译通过}
成员函数模板
1.普通的类包含成员模板
class B{public:template <typename T>void fun(T input)//类内定义{cout<<input<<endl;}};//定义template <typename T>void B::fun() //类外定义成员函数,B后无尖括号{}
2.类模板的成员函数模板
template <typename T>class B{public:template <typename T2>void fun(T2 input)//类内定义{内部可以使用T,T2}};//定义template <typename T>template <typename T2>void B<T>::fun() //类外定义成员函数,两层template{}int main(){B<int>x;x.fun<float>(3.0);}
类模板实例化

namespace N{template<typename T>class Y{void mf(){}};}using N::Y;template class N::Y<char*>; //实例化template void N::Y<double>::mf(); //只实例化成员函数
类模板特化:重要
template<typename T>class B{void fun(){}};template<>class B<int> //特化版本{void fun(){}};

