函数模板显式具体化、显式实例化
显式实例化声明
使用foo()模板生成一个int类型的函数定义。实例化:从一个模板里出来的,大家都是一样的。
显式具体化声明
不要使用foo()模板来生成函数定义,而应该使用专门为int类型显式定义的函数定义。这些原型必须有自己的函数定义,相当于函数重载。具体化:各有各的不同。
// 函数模板
template<typename T>
void foo(T t)
{
...
}
// 显式具体化
template<>
void foo<char*>(char* pstr); // 后面要给出定义,否则调用会报链接错误:函数未定义
/**
* 等价形式
* template<>
* void foo(char* pstr);
* 两者仅能使用一种,否则会引起函数名重定义的错误
*/
// 显式实例化,foo(T t)为其生成函数定义
template void foo<int>(int i);
// 显式具体化(自己实现)
template<>
void foo<double>(double d)
{
...
// 不同于函数模板的实现方式
}
// 调用
int main()
{
int i = 10;
double d = 1.2;
float f = 1.4;
foo(f); // 隐式实例化,调用的时候,根据实参类型,生成模板函数实例
foo(d); // 调用foo<double>(double d),如果没有给出定义,会报链接错误;
// 其自身不会再去根据模板来生成实例
foo(i); // 调用foo(T t)根据int类型生成的实例foo<int>(int t)
}
第一个:显式实例化,在main
之前,foo
函数模板就为foo<int>
创建了定义
第二个:显式具体化,使用double
类型重载了foo
函数模板
第三个:隐式实例化,在main
函数中调用时,根据实参类型实例化的模板函数
函数模板的特化必须是全特化,指定为具体某个类型。如果嵌套在类模板里,若将函数模板具体化,则需要在类内定义;若将函数模板实例化,只需将其显式实例化声明。如:
// 嵌套类模板,将函数模板具体化
template<typename T>
void eat(T t);
template<typename T>
class Cat
{
public:
friend void eat(Cat<T>& t)
{
// do something, override
}
private:
T food;
}
// 嵌套类模板,将函数模板实例化
template<typename T>
void eat(T t)
{
// do something
}
template<typename T>
class Cat
{
public:
friend void eat<> (Cat<T>& t)
private:
T food;
}
匹配规则优先级
显式调用 > 隐式调用
具体 > 模糊