函数模板
//定义
template <typename T>
T max(T a, T b)
{
return a > b ? a : b;
}
//使用
int a, b, c;
a = 10;
b = 20;
c = max(a, b); //自动选择使用普通函数还是模板
c = max<>(a, b); //强制使用模板
c = max<int>(a, b); //强制使用模板并指定实例化类型
要点
- 函数模板的模板参数不支持默认值
类模板
//定义
template <typename T>
class Compare
{
public:
T max(T a, T b);
};
//实现
template <typename T>
T Compare<T>::max(T a, T b)
{
return a > b ? a : b;
}
//使用
int a, b, c;
a = 10;
b = 20;
Compare<int> comp; //必须显式指定模板参数类型
c = comp.max(a, b);
特化
完全特化
//定义
template <>
class Compare<int>
{
public:
int max(int a, int b);
};
//实现
int Compare<int>::max(int a, int b)
{
return a > b ? a : b;
}
局部特化
//原模板定义
template <typename T1, typename T2>
class Test {};
//特化1
template <typename T>
class Test<T,T> {};
//特化2
template <typename T>
class Test<T,int> {};
//特化3
template <typename T1, typename T2>
class Test<T1*,T2*> {};
参数
模板参数
模板参数可以有默认类型值,可以是模板的实例
//定义
template <typename T, typename CONT = std::vector<T> >
class Test {};
非模板参数
//定义
template <int SIZE = 128>
class Test
{
private:
char buffer[SIZE];
};
//使用
Test<32> t;
注意事项
- 非模板参数只能使用整数类型或指向外部连接的指针
- 字符串常量不能作为非模板参数的实参 Test<“abc”> t;
- 非模板参数的实参不能是全局指针
模板的模板参数
//定义
template <typename T,
template <typename TT> class CONT = std::vector >
class Test
{
private:
CONT<T> buffer;
};
//使用
Test<32> t;
一些坑
注意尖括号
避免将模板中的尖括号写到一起变成了位操作的符号,应当适当添加空格
typename
template <typename T>
void test(T t)
{
//如果这里没有使用typename关键字,T::itor将会初当成T的静态成员名而不是内部类型名
typename T::itor it = t.first();
}
.template
模板在继承时的内部指向
在子类模板中调用 fn() 并不会调用父类模板中定义的fn成员函数,而是尝试调用了全局函数fn或者报错,所以需要使用this->fn()或者ParentClass::fn()来代替
成员模板
类模板的成员函数或者内嵌类可以是模板
//定义
template <typename T>
class Test
{
public:
template <typename T2>
void fn(T2 t2);
};
//实现
template <typename T>
template <typename T2>
void Test<T>fn(T2 t2)
{
}
静态类型的初始化
template <typename T>
void test()
{
//如果T是一个静态类型比如int,如果不初始化会得到一个随机初始值,所以使用T()的形式初始化
T t();
}
字符串引用问题
template <typename T>
T test(T &t1, T &t2)
{
return t1 > t2 ? t1 : t2;
}
//下面的用法将会报错,因为两个实参的类型分别是char[4]&和char[5]&而不是(const char *)&,如果不使用引用类型参数即可解决
test("abc", "defg");