函数模板会进行严格的类型匹配,模板类型不提供隐式类型转化
普通函数能够进行自动类型转换
函数模板重载四大规则
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
4 可以通过空模板实参列表的<>语法限定编译器只通过模板匹配
5 模板的实例化类型确定是在编译期间
6 函数查找顺序:1,找普通函数或类;2,如果1找不到,则找模板.3,如果2找到模板,就找匹配度高(特化)模板或特殊模板.4,如果3找不到,则使用普通模板.
7 特例化本质上我们顶替了编译器的工作,帮编译器做了类型推导.类的偏特化本质上还是一个模板,是源模板的一个子集.而全特化则是一个实例(但仍是模板).
8 因为是编译器的工作,因此,一系列特化版本必须与源模板在一个文件中
9 特化的类型可以是const T*, T&, const T&, T*等
10 模板参数:和函数参数类似.如template 如template
11 函数模板不是函数,而是模板.
模板特化按对象类型(类和函数)分为两种:类模板特化和模板函数的特化。
类模板有偏特化 因为类不能重载
函数模板没有偏特化 因为函数能重载
特化与偏特化可以理解为模板的实例化程度。
//类模板
template
class D
{
public:
void test()
{
cout << "类模板无特化 又称为基础类模板 " << endl;
}
};
//类模板的偏特化 指明了一部分类型 class D class D class D
template
class D
{
public:
void test()
{
cout << "类模板的偏特化" << endl;
}
};
//类模板的全特化 指明了全部类型
template<>
class D
{
public:
void test()
{
cout << "类模板的全特化" << endl;
}
};
void main1()
{
D d1;//无特化
d1.test();
D d2;//偏特化
d2.test();
D d3;//全特化
d3.test();
162 }
void test(int a, char *p)
{cout << "普通函数" << endl;}
template
void test(T1 t1, T2 t2)
{cout << "普通函数模板" << endl;}
template<>
void test(int t1, char *t2)
{cout << "函数模板全特化" << endl;}
void main2()
{
int a;
char *p;
test(a,p);//普通函数
test<>(a,p);//函数模板全特化 <>使其使用函数模板
test(a,p);//函数模板全特化
test<>(a,a);//普通函数模板
//尝试定义偏特化,结果出错.C++不允许其存在.
}
训练:
- template<typename T> void f(T);
- template<typename T> void f(T*);
- template< > void f<int>(int*);
- int* p;
- f(p);
- 1,
-
- template<typename T> void f(T);
- template< > void f<int*>(int*);
- template<typename T> void f(T*);
- int* p;
- f(p);
-
答案:c,c
解析:
1,a,b是基础模板,b的匹配度更高,因此选择了b;c是b的特化,并且匹配,因此最终选择了c
2,a,c是基础模板,c的匹配度更高,而c无特化版本,因此最终选择了c.
//基础模板
//template
//void test1(T t)
//{cout << "a" << endl;}
//基础模板
template
void test1(T *t)
{cout << "b" << endl;}
//基础模板
template
void test1(T &t)
{cout << "c" << endl;}
//明显是a的全特化
//template<>
//void test1(int *p)
//{cout << "1" << endl;}
//明显是b的全特化
template<>
void test1(int *p)
{cout << "2" << endl;}
//明显是c的全特化
template<>
void test1(int &)
{cout << "3" << endl;}.
void main3()
{
int n = 1;
test1(n);//多义:a和c 注释掉其中一个后:3
int *p = &n;
//先匹配基础模板,发现b最合适.便以b为基础进行特化模板挑选
test1(p);//2
test1(&p);//b
test1(&n);//2
}
此外,还有特殊的模板,后期我会慢慢总结.
c++11新特性:可变模板参数:可变模板参数函数和可变模板参数类.