- 默写情况下,通用定义可能编译失败或做得不对
- 当我们不能使用模板版本时,我们可以定义类或函数模板的一个特例化
- 考虑下边代码
template<typename T>int compare(const T&,const T&);
template<size_t N,size_t M>
int com[are(const char(&)[N],const char(&)[M]);
const chat *p1 = "hi", *p2="mon";
compare(p1,p2);
compare("hi","mon");
- 只有传递给compare一个字符串字面常量或一个数组时,编译器才会接受第二个版本。
- 如果传递个字符指针,就会调用第一个版本
- 为了处理字符指针,可以为第一个版本的compare定义一个模板特例化版本
- 一个特例化版本就是一个独立的定义,其中一个或多个模板参数被指定为特定的值
定义模板特例化
- 特例化函数模板时必须为原模板中每个模板参数都提供实参
- 关键字template后跟空<>指出我们将要为原模板的所有模板参数提供实参
template<>
int compare(const char* const &p1,const char* const &p2)
{
return strcmo(p1,p2);
}
- 定义一个特例化版本时,函数参数类型必须与一个先前声明的模板中对应的类型匹配
- 原模板实参要求是一个指向类型T的const版本的引用
- const char* const &表示一个指向const char*的const指针的引用
函数重载与模板特例化
- 一个特例化版本本质上是一个实例,而不是函数名的一个重载版本
- 为了特例化一个模板,原模板的声明必须在作用域内,而且在任何使用模板实例的代码之前,特例化版本也必须在作用域内
类模板特例化
- 类模板特例化以template更空<>开头
- 可以在类内或类外定义特例化版本成员
类模板部分特例化
- 与函数模板不同,类模板的特例化不必为所有模板参数提供实参
- 可以只指定一部分而非所有模板参数,或参数的一部分而非全部特性
- 一个类模板的部分特例化本身是一个模板,使用时,用户必须为那些在特例化中为指定的模板参数提供实参
- 部分特例化模板参数列表是原模板参数列表的一个自己或者是一个特例化版本
template<class T>struct remove_reference
{
typedef T type;
};
template<class &T>struct remove_reference
{
typedef T type;
};
template<class &&T>struct remove_reference
{
typedef T type;
};
特例化成员而不是类
template<type name T>struct Foo{
Foo(const T &t = T()):men(t){}
vois bar(){};
T men;
};
template<>
void Foo<int>::bar()
{}