而是对于实例化模板参数的每种类型,都从模板产生出一个不同的实体。
这种用具体类型代替模板参数的过程叫做实例化。它产生了一个模板的实例。
编译器使用模板为特定类型生成函数(类)定义时,得到的就是模板实例。
template <typename T>
T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
实例化其实就是模板最普通的写法
使用关键字template并指出所需类型来声明类时,编译器将生成类声明的显式实例化。
(显示生成一个类型的实例)
template <typename T>
inline T max (T a, T b)
{
return a < b ? b : a;
}
template int max<int>(int a, int b); //显式实例化,指定编译器生成int类型的模板定义
template int max<>(int a, int b); //简写
template int max(int a, int b); //简写
显式实例化只是一个声明,让编译器用具体的类型生成函数定义或类定义。
用处:
在多文件编译连接时生成实例
//t1.h
template <typename T>
void f(T x);
//t1.cpp
#include "te.h"
#include <iostream>
template <typename T>
void f(T x)
{
std::cout << x << std::endl;
}
template void f<int>(int);//显式实例化int
//main.cpp
#include "te.h"
#include <iostream>
int main()
{
f(6); //编译成功,输出6
//编译失败,undefined reference to `void f<char>(char)'
f('6');
return 0;
}
上述代码用显示实例化生成了int的函数而没有生成char的,从而报错char类型的未定义
函数模板特化指函数模板在模板参数为特定类型下的特定实现
模板的特化和函数类模板的重载类似,你可以依次重写这个函数或者类, 也可以只特化某个成员(片特化),也可以特化整个类(全特化)
在起始处声明一个 template<>,接下来声明用来特化类模板的类型。这个类型被用作模板实参,且必须在类名的后面直接指定
template<>
class A<int>{
....
};
进行类模板的全特化时,每个成员函数都必须重新定义为普通函数,原来模板函数中的每个T也相应地被进行特化的类型取代:
#include <iostream>
//模板
template <typename T>
class A{
public:
void get(){std::cout << "common" << std::endl;}
};
template<>
class A<int>{
public:
void get(){std::cout << "int template" << std::endl;}
};
int main()
{
A<std::string> a;
a.get(); //common
A<int> aa;
aa.get(); //int template
return 0;
}
注意:
全特化和由模板生成的实例化不能存在于同一个程序中。
template <typename T>
class A {
public:
};
template class A<double>;
//错误,必须在其首次使用之前对 类 \"A<double>\" 进行显式专用化
template<>
class A<double>
{
};
template<typename T>
int f(T) { return 1; }
template<> int f<int>(int) { return 3; } //完整写法
template<> int f(int) { return 3; } //简写,省略了<int>
模板偏特化是模板特化的一种特殊情况,指显示指定部分模板参数而非全部模板参数,或者指定模板参数的部分特性分而非全部特性,也称为模板部分特化。
//类模板
template <typename T1, typename T2>
class MyClass {
...
};
//局部特化:两个模板参数具有相同的类型
template <typename T>
class MyClass<T,T> {
...
};
//局部特化:第2个模板参数的类型是int
template<typename T>
class MyClass<T,int> {
...
};
局部特化:两个模板参数都是指针类型。
template<typename T1,typename T2>
class MyClass<T1*,T2*>{
...
};
调用:
Myclass<int,float> mif; //使用MyClass<T1,T2>
MyClass<float,float> mff; //使用MyClass<T,T>
MyClass<float,int> mfi; //使用MyClass<T,int>
MyClass<int*,float*> mp; //使用MyClass<T1*,T2*>
实例
#include <iostream>
#include <string>
template <typename T1, typename T2>
class MyClass
{
public:
MyClass(const T1& t1, const T2& t2) { std::cout << "111: " << t1 << std::endl; }
};
//显示具体化、特化
template<>
class MyClass<std::string, std::string>
{
public:
MyClass(const std::string& t1, const std::string& t2) { std::cout << "222 : " << t1 << std::endl; }
};
//部分特化
template <typename T1>
class MyClass<T1, double>
{
public:
MyClass(const T1& t1, const double& t2) { std::cout << "333 : " << t1 << std::endl; }
};
//显示实例化
template class MyClass<std::string, int>;
int main()
{
MyClass<char[3],std::string> class2("s2", "s22");
MyClass<std::string,std::string> class3("s3", "s33");
MyClass<std::string,double> class4("s4", 3.14);
return 0;
}
输出
111: s2
222 : s3
333 : s4