1. 模板特例化
某些特例情况,通用函数模板无法处理,需要定义特定的模板。
如需比较两个数字或字符串的大小,可为数字的比较提供如下的函数模板:
template<typename T>
bool compare(T a, T b) {
return a > b;
}
void test01() {
compare(10, 20);
}
但使用上面函数模板比较两个字符串:
compare("aaa","bbc");
则比较的是两个字符串的地址,而不是字典顺序,违背本意。
因此为字符串的比较提供模板特例化,如下:
template<>
bool compare<const char*>(const char* a, const char* b) { // 完全特例化
return strcmp(a, b) > 0;
}
注意:
(1)不能单独提供模板特例化,必须提供主模板;
(2)主模板必须在特例化模板之前声明;
(3)模板特例化与主模板的形参个数、顺序、类型必须一致。
第(3)点说明:
若主模板是:
template<class T, int N>
class A {
};
那么完全特化模板可以是:
template<>
class A<double, 10> {
};
不能是如下两个:
template<>
class A<10, double> {
};
template<>
class A<double> {
};
1.1 完全特例化 和 部分特例化
/*完全特例化*/
template<>
class Vector<char*> { // char*类型
public:
Vector() { cout << "完全特例化" << endl; }
};
/*部分特例化*/
template<typename T>
class Vector<T*> { // 指针类型,但不确定什么类型的指针
public:
Vector() { cout << "部分特例化" << endl; }
};
void test04() {
Vector<int> v1; // 主模板
Vector<char*> v2; // 完全特例化
Vector<int*> v3; // 部分特例化
Vector<int(*)(int)> v4; // 部分特例化
}
2. 模板实参推导
template<typename T>
void infer(T a) {
cout << typeid(T).name() << endl;
}
template<typename R, typename A, typename B>
void infer(R(*)(A a, B b)) {
cout << typeid(R).name() << " " << typeid(A).name() << " " << typeid(B).name() << endl;
}
int mul(int a, int b) { return a * b; }
void eat(string a) {}
void test05() {
infer(10); // int
infer("abc"); // char const * __ptr64
infer(mul); // int int int
infer(eat); // void (__cdecl*)(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)
}