chapter 13.pdf
函数模板
声明:不带大括号,可以多次声明
定义:带大括号,只能定义一次
template<typename T> void fun(T); //声明,可用class代替typename
template<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;
}
//可以将定义与声明分开,只开放定义接口给用户
template
void 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"
template
void 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;
}
template
void fun(int* x); //实例化为第一个模板函数,
template <typename T>
void fun(T* x)
{
cout<< x <<endl;
}
template
void fun(int* x); //实例化为第二个模板函数,形参推导为离当前实例化近的定义
template
void fun<int*>(int* x); //实例化为第一个模板函数,因为int*和参数列表的int*一致,T = int*
int main()
{
}
函数模板的特化
#include<iostream>
template<typename T>
void fun(T x)
{
cout<<x<<endl;
}
//可以将定义与声明分开,只开放定义接口给用户
template
void 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(){}
};