函数模板
上一篇文章简单的介绍了类模板的入门语法,现在我们来了解一下函数模板,函数模板与类模板可以说大同小异,同样以template<class T> 作为开始,表明接下来声明或者定义的是一个模板。
- 在函数模板中,定义语法如下
template<class T,class U>
Void function(T t, U u)
{
//body;
}
- 什么时候使用函数模板?
比如中国人吃饭用手,外国人吃饭用叉子,印度人吃饭用手,所以吃饭这个行为是大家都有的,只是在具体的方式上因主体对象的差别有些许不同,那么为这些主体分别展开编程会让代码膨胀,使抽象性变差。这个时候我们只需要一个函数模板将吃饭的行为抽象化,只需要考虑将主体对象作为类型参数传入完成这一行为就行。
- 函数模板的实例化
我们现在定义了这样的函数
template <typename T> void Swap(T a, T b)
{
T tmp=a;
a=b;
b=tmp;
}
可以这样使用
Swap<int>(a,b);
也可以这样
Swap(a,b);
实际上第二种方式是编译器使用了隐式推导,但前提是得保证a,b的类型一致,否则编译器也不知道该听a的话,还是b的话。另外,编辑器无法根据返回的类型进行推导
float data[1024];
template <typename T> T GetValue(int i)
{
return static_cast<T>(data[i]);
}
float a = GetValue(0); // 出错了!
int b = GetValue(1); // 也出错了!
另外,编译器的隐式推导是可以进行部分推导的,不过需要把推不了类型传进模板,比如上面只存在于返回的类型。总之新手还是先老老实实用显示调用吧。
实际上,如果不犯这种错误,可能编译器比你想的强大的多,甚至可以这样猜出你的意图
template <typename T> class A {};
template <typename T> T function( A<T> v );
A<int> v;
function(v); // 它能准确地猜到 T 是 int.
- 整形数也能成为模板参数
这里的整形非常宽泛,从布尔型,不同位数、有无符号的整型,甚至到包括指针。
template <typename T, int Size> struct Array
{
T data[Size];
};
Array<int, 16> arr;
但要注意,正如之前将的模板实例化必须在编译期完成,所以凡是在运行期才能确定整形的值或者类型都将引发错误