先看代码,分析调用情况:
1 #include<iostream>
2
3 using namespace std;
4
5 template <typename T1,typename T2>
6 void test_fuc(T1& t1, T2& t2)
7 {
8 cout << "template...
";
9 }
10
11 template <typename T>
12 void test_fuc(T& t1, T& t2)
13 {
14 cout << "template...
";
15 }
16
17 void test_fuc(int a, char b)
18 {
19 cout << "ordinary fuction...
";
20 }
21
22 int main()
23 {
24 int a = 1;
25 char b = 0;
26 test_fuc(a, b);
27 test_fuc(a, a);
28 test_fuc(b, a);
29 cout << "hello...
";
30 return 0;
31 }
函数模板,也可以重载。当函数模板和普通函数名一样时,调用规则是:
1.如果普通函数和函数模板都有完全匹配的参数,优先调用普通函数的,如上面26行代码。
2.函数模板的参数必须严格一致,不能发生隐式转换,但是普通函数可以有隐式类型转换。这个测试需要把上面第一个模板函数屏蔽,调用28行代码,将访问普通函数,因为模板函数不能有隐式转化,必须严格匹配,普通函数则不同。
3.如果函数模板可以产生一个更好的匹配,优先调用函数模板。具体来说,27行代码,通过隐式类型转化其实是可以调用普通函数的,但是因为有一个完全匹配的模板函数,所以此时优先调用模板函数。
4.可以通过模板实参列表的语法限定编译器只通过模板匹配。
举例说明第四点(这也是为什么不动手就学不好c/c++的原因,这个也是因为自己在测试时发现的):
1 template <typename T>
2 void test_fuc(T t1, T t2)
3 {
4 cout << "template...
";
5 }
6
7 void test_fuc(int a, int b)
8 {
9 cout << "ordinary fuction...
";
10 }
11
12 int main()
13 {
14 int a = 1;
15 char b = 0;
16 test_fuc(a, a);
17 test_fuc<>(a, a);
18 //test_fuc<int>(a,a);
19 cout << "hello...
";
20 return 0;
21 }
通过前面的几点分析可以知道,16行的调用将优先匹配普通函数,但要是我们就想调用模板函数,可以像17行那样,加一个空的模板参数列表,让其调用模板函数,也可以显式参数类型,如18行那样都可以让其绕过普通函数而强制调用模板函数。
再测(注意参数类型我已经更改):
1 template <typename T>
2 void test_fuc(T t1, T t2)
3 {
4 cout << "template...
";
5 }
6
7 void test_fuc(int a, char b)
8 {
9 cout << "ordinary fuction...
";
10 }
11
12 int main()
13 {
14 int a = 1;
15 char b = 0;
16 test_fuc(a, b);
17 test_fuc<int>(a, b);
18 //test_fuc<>(a, b);
19 cout << "hello...
";
20 return 0;
21 }
第16行调用普通函数无可非议,17行,通过模板参数列表强制让其调用int类型的参数,这样也可以调用隐式转化过的模板函数,上面说的模板函数不能隐式转化,必须完全匹配是建立在隐式调用模板函数的前提下,通过模板参数列表显式调用模板函数,还是可以达到隐式转换的效果。但此时不能用空的模板参数,例如18行那样的调用会报错,要隐式转换你也得提供一个转换类型啊。
再改:
1 template <typename T>
2 void test_fuc(T& t1, T& t2)
3 {
4 cout << "template...
";
5 }
将模板函数参数换成引用,此时上面的代码将报错,不能从char转换到int &,这说明,模板函数的隐式转化和普通函数一样,必须要是可以隐式的类型,我们本就不能把一个char类型的绑定给一个int类型的引用。
再把上述引用类型改成指针,调用
test_fuc<int>(&a, &b);
同样报错,不能从char*转化成int*;可见,隐式类型转化的原则模板函数和普通函数都是需要遵循的。我们可以int和char或者double这样的转换,但是不可以用c++语言不支持的隐式类型转化规则。