函数模板提供了一种函数行为,该函数行为可以表示成多种类型进行调用,也就是说函数模板表时一个函数家族。
那函数模板要怎么写呢?
template<typename T>
T max(const T& t1, const T& t2) {
return t1 > t2 ? t1 : t2;
}
函数模板有两种类型的参数:
模板参数:
template<typename T>
调用参数:
T max(const T& t1, const T& t2) {
return t1 > t2 ? t1 : t2;
}
这是我们就会想普通的函数是可以重载的,那模板函数可以重载吗?
template<typename T>
T max(const T& t1, const T& t2) {
return t1 > t2 ? t1 : t2;
}
int max(const int& t1, const int& t2) {
return t1 > t2 ? t1 : t2;
}
这是有人会发出疑问?但我们实例化这个函数模板时,如果与非模板函数完全相同,那会不会产生二义性呢?,解决这个问题之前让我们先看看函数模板怎么实例化?
int main(void)
{
int t1 = 1, t2 = 2;
max<int>(t1, t2);
max(t1, t2);
}
函数模板的实例化一般存在两种,只有使用第二种函数模板实例化时才会出现我们刚刚说的那种问题。好了,现在让我们说一下原因吧。
对于非模板函数和同名的模板函数,实例化后的模板函数如果与非模板函数完全相同,那么在调用的时候,编译器会默认为你调用的时非类型的。为什么呢?我是这样理解的:函数模板的实例化是需要花费时间和空间的,编译器肯定会选择时间与空间开支较少的。
其实函数模板也可以进行特化的,很惊讶吧!!
template<>
int max<int>(const int& t1, const int& t2) {
return t1 > t2 ? t1 : t2;
}
还可以偏特化哦!
template<typename T,typename U>
T max(const T& t1, const T& t2) {
return t1 > t2 ? t1 : t2;
}
template<typename T>
int max<T,int>(const int& t1, const int& t2) {
return t1 > t2 ? t1 : t2;
}
template<typename T,typename U>
int max<T*, U*>(const T& t1, const U& t2) {
return t1 > t2 ? t1 : t2;
}