函数模板

//定义
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");