1.什么是函数模板?
函数模板是通过模板来实现family function,模板参数的类型可以是任意的。
2.怎么使用模板
1.使用模板时,模板参数或类型会被替换,该过程称为实例化。
2.注意,模板类型可以为void*
3.模板编译过程分为两个步骤
1.检测是否有语法错误,是否有使用未知的参数,静态断言不依赖于模板参数的
2.实例化,该过程会再次检查所有参数
举一个例子:
template<typename T>
void foo(T t){
declare();//第一次会检查declare是否存在(也就是是否合法)
declare(t);//第二次检查declare是否合法,同时检查参数是否合法
static_assert(sizeof(t)>10);//只会在实例化阶段检查是否合法
static_assert(sizeof(int)>10);//第一次就会检查是否合法
}
注意:1.有些编译器不会严格执行这个检查规范,目前知道msvc和gdb是遵守的
3.模板参数推导
template<typename T>T max(T const&a,T const&b){
return a<b?a;b;
}
template<typename T> void deduction(T a){
}
1.对于max函数,如果实例化为max(1,2);那么T的类型将会被推到为int。
2.对于deduction函数而言,将会出现类型退化的特征(参数类型为值)特征如下:
int a;
int b[10];
int &d=a;
int &&c = std::move(a);
deduction(&a);//T type int*
deduction(a);//T type int
deduction(b);//T type int*
deduction(c);//T type int
deduction(d);//T type int
4.默认参数推导
template<typename T>void foo(T = ""){
}
foo(1) //ok!
5.多参数模板
1.和前面的例子一样
template<typename T1,typename T2>void f(T1 a,T2 b){
}
2.可能遇到的问题
template<typename T1,typename T2>T1 max(T1 a,T2 b){
return a>b?a:b;
}
可能已经注意到,如果我调用max(1,2.5),返回的会是2(小数转换为整数会向下取整);那么应该怎么解决这个问题呢?
3.解决问题
1.新增一个参数判断返回值
template<typename T3,typename T1,typename T2>T3 max(T1 a,T2 b){
return a>b?a:b;
}
调用方式 max<double,int,double>(2,2.5); //太麻烦了!
或者调用 max<double>(2,2.5);//依然有点麻烦!
2.让编译器自动判断返回值
//这种写法要是c++14之后
template<typename T1,typename T2>auto max(T1 a,T2 b){
return a>b?a:b; //很方便!
}
//c++14之前
template<typename T1,typename T2>auto max(T1 a,T2 b)->decltype(a>b?a:b){
return a>b?a:b;
}
3.返回一个common_type_t
#include <type_traits>
template<typename A,typename B>std::common_type_t max(A a,B b){
return a>b?a:b;
}
6.默认参数
template<typename T,typename T1,typename RT = std::decay_t<std::decltype(true?a:b)>>//注意:decay防止返回引用
RT max(T a,T1 b){
return a>b?a:b;
}
7.优先匹配
template<typename T> void func(T t) {
}
template<typename T>void func(T* t) {
}
int a = 10;
func(&a)//对于这个调用会优先匹配T*的函数
8.关于constexpr,自c++11之后,使编译期的计算成为可能
template<typename T> constexpr auto array(T t){
return t;
}
int a[array(10)];//正确