理解函数模板

函数模板的意义:对类型也可以参数化
int sum(int a, int b) {
return a + b;
}
int 定死
函数模板让参数类型可变

  1. 函数模板 不进行编译
  2. 模板的实例化 在函数调用点编译
  3. 模板函数 需要编译
  4. 模板类型参数
  5. 模板非类型参数
  6. 模板的实参推演=>模板根据实参推导函数实例
  7. 模板的特例化(专用化)
  8. 函数模板、模板的特例化、非模板函数的重载关系
1
2
3
4
5
6
7
//函数模板,不编译
template<typename T> //定义一个模板参数列表

bool compare(T a, T b) { //compare是一个函数模板
cout<<"template compare"<<endl;
return a > b;
}

函数的调用点,编译器用用户指定的类型,从原模版实例化一份函数代码出来
即模板函数
bool compare(int a, int b)
{
return a > b;
}
bool compare(double a, double b)
{
return a > b;
}

bool compare(const char a, const char b)
{
return a > b;
}
此处比较的是ab的地址大小,我们应该比较字符串的内容
这个根据模板推演的模板函数不是我们想要的,因此需要我们特例化
针对compare函数模板,提供const char*的特例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//前面还是需要函数模板
template<> //模板的专用化模板
bool compare<const char*>(const char* a, const char* b)
{
cout<<"compare<const char*>"<<endl;
return strcmp(a,b) > 0;
}

//普通函数
bool compare(const char* a, const char* b)
{
return strcmp(a,b) > 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main() {
//函数调用点
compare<int>(10,20)
compare<double>(10.1,20.2)

//模板的实参推演=>模板根据实参推导函数实例
//无对应的模板函数则实例化,有则直接调用
compare(10.1,20.2)

//int ,double 报错,无对应的模板函数
compare(10,20.1);
//强制把后一个参数转为int
compare<int>(10,20.1)


//这里是模板实参推演,T const char*
compare("aaa","bbb");
//若有普通函数符合条件,优先调用普通函数



}

对于某些类型来说,依赖编译器默认实例化的模板代码,代码处理逻辑是错误的

模板的特例化(专用化)
不是编译器,而是开发者提供的

1
2
3
4
5
6
template<>  //模板的专用化
bool compare <const char*>(const char* a, const char* b)
{
cout<<"compare<const char*>"<<endl;
return strcmp(a,b) > 0;
}

多文件

在多文件工程时,将函数定义放在test.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename T>  //定义一个模板参数列表

bool compare(T a, T b) { //compare是一个函数模板
cout<<"template compare"<<endl;
return a > b;
}

template<> //模板的专用化模板
bool compare<const char*>(const char* a, const char* b)
{
cout<<"compare<const char*>"<<endl;
return strcmp(a,b) > 0;
}

//普通函数
bool compare(const char* a, const char* b)
{
return strcmp(a,b) > 0;
}


test2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
//模板声明
template<typename T> //定义一个模板参数列表
bool compare(T a, T b)
int main() {
compare<int>(10,20)
compare<double>(10.1,20.2)
compare(10.1,20.2)
compare<int>(10,20.1)
compare("aaa","bbb"); //无报错
compare<const char*>("aaa","bbb");//无报错,其余都报错
}

结论:

模板在跨文件时,由于模板是不编译的,即使声明了模板,也找不到对应的代码
对于特例化的模板函数,声明了模板,就能找到
也不用管那么多,模板代码放在头文件中,在源文件中进行#include包含,这样源文件一定能看见模板代码

ps:也可以让编译其对模板进行实例化
c++ template bool compare<int>(int a, int b); 对这种模板函数进行实例化