先来个例子:
1 #include <iostream> 2 3 using namespace std; 4 5 6 template <class t1,class t2> 7 t1 ff(t1 a,t1 b,t2 c) 8 { 9 cout<<a+b<<' '<<c<<endl; 10 return 0; 11 } 12 13 int main() 14 { 15 ff(1,2,3.1); 16 ff(1.2,2.0,'a'); 17 return 0; 18 }
需要注意的地方有:
1.template关键字表示声明的是模板。
2.<>中时模板的参数表,可以有一项或多项,其中的类型名称为参数化类型,是一种抽象类型或可变类型。
3.class是类型关键字,也可以用typename作为关键字。
4.函数返回值类型可以是普通类型,也可以是模板参数表中指定的类型。
5.模板参数表中的参数类型可以是普通类型。
函数模板定义好后,即可生成各种具体的函数,该过程称之为实例化。函数模板实例化分为显式实例化与隐式实例化。(前面的例子即为隐式实例化)
显式实例化举例:
1 #include <iostream> 2 3 using namespace std; 4 5 6 template <class t1,class t2> 7 t1 ff(t1 a,t1 b,t2 c) 8 { 9 cout<<a+b<<' '<<c<<endl; 10 return 0; 11 } 12 13 int main() 14 { 15 ff<int,double>(1,2,3.1); 16 ff<double,char>(1.2,2.0,'a'); 17 return 0; 18 }
注意一点:当程序里同时出现重载函数和函数模板时,优先绑定重载函数,若是不能精确匹配,方匹配函数模板。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
class A { template <typename T, typename = typename std::enable_if<std::is_integral<typename std::remove_reference<T>::type>::value>::type> void f (const std::string& key, T value); }; template <typename T, typename V> inline void A::f (const std::string& key, T value) { /// }
这里是一个项目中用到的例子,T是整数类型,is_integral包含所有整数类型,remove_reference是去引用(如果不这样做,调用方传参带引用,匹配会失败,因为带引用的type与指针类似,不能称之为整数),类外实现带的声明与类内差异很大,V仅仅用作形式上与类内声明保持匹配,没有实际意义。
另外需要注意的是,模板默认内联,必须把实现体放在对应头文件里。