C++模板与泛型 --- 模板全特化、偏特化(局部特化)
2019-06-09 本文已影响3人
307656af5a04
一、类模板特化
特化与泛化相反,泛化可以随便指定类型
特化就是对特殊的类型(类型模板参数)进行特殊的对待,给它写适合它的专用代码。
1、类模板全特化
a、常规全特化
#include <iostream>
#include <string>
using namespace std;
template <typename T,typename U>
struct TC // 泛化的TC类模板
{
TC()
{
cout << "泛化版本构造函数" << endl;
}
void functest()
{
cout << "泛化版本" << endl;
}
};
// 当T与U这两个类型模板参数都为int类型时,我们希望做一个特化版本
// 全特化就是所有类型模板参数,都需要用具体的类型代表
// 全特化表示所有类型模板参数都用具体类型代表,
// 所以这里template后面的<>里为空
template <>
struct TC<int,int> // 上面的T绑定到第一个int,上面的U绑定到第二个int
{
TC()
{
cout << "特化版本构造函数" << endl;
}
// 对特化版本进行单独处理
void functest()
{
cout << "int,int的特化版本" << endl;
}
};
// 当T与U这两个类型模板参数都为int类型时,我们希望做一个特化版本
// 全特化就是所有类型模板参数,都需要用具体的类型代表
// 全特化表示所有类型模板参数都用具体类型代表,
// 所以这里template后面的<>里为空
template <>
// 上面的T绑定到第一个double,上面的U绑定到第二个int
struct TC<double, int>
{
void functest()
{
cout << "double,int的特化版本" << endl;
}
};
int main()
{
// 调用int,int特化版本
TC<int, int> dc;
dc.functest();
// 调用泛化版本
TC<char, int> tchar;
tchar.functest();
system("pause");
return 0;
}
b、特化成员函数而不是模板
// 全特化
template <>
void TC<double, double>::functest()
{
cout << "double,double特化版本函数";
}
// 调用
// 调用的是泛化版本的构造函数
TC<double, double> dx;
// 调用的是特化版本的函数
dx.functest();
2、类模板偏特化(局部特化)
偏特化从两个方面说起:一个是从模板参数数量上,一个是从模板参数范围上
a、模板参数数量
#include <iostream>
#include <string>
using namespace std;
template <typename T,typename U, typename W>
struct TC // 泛化的TC类模板
{
TC()
{
cout << "泛化版本构造函数" << endl;
}
void functest()
{
cout << "泛化版本" << endl;
}
};
// 从参数数量上进行偏特化,绑两个类型模板参数,留一个类型模板参数
template <typename U>
struct TC <int,U, int>
{
TC()
{
cout << "偏特化版本构造函数" << endl;
}
void functest()
{
cout << "偏特化int,U, int版本" << endl;
}
};
int main()
{
// 偏特化版本
TC<int, int, int> dc;
dc.functest();
system("pause");
return 0;
}
b、模板参数范围
int --> const int (比int范围小)
T --> T(从任意类型T缩小为指针类型T)
T --> T&(左值引用)或者T&&(右值引用)都叫范围缩小
#include <iostream>
#include <string>
using namespace std;
template <typename T>
struct TC // 泛化的TC类模板
{
TC()
{
cout << "泛化版本构造函数" << endl;
}
void functest()
{
cout << "泛化版本" << endl;
}
};
// 模板参数范围上的特化版本
template <typename T>
struct TC<const T>
{
TC()
{
cout << "const类型特化版本构造函数" << endl;
}
void functest()
{
cout << "const类型特化版本" << endl;
}
};
// 模板参数范围上的特化版本
template <typename T>
struct TC<T*>
{
TC()
{
cout << "指针类型偏特化版本构造函数" << endl;
}
void functest()
{
cout << "指针类型特化偏版本" << endl;
}
};
int main()
{
// 模板参数范围上的特化版本
TC<const int> dc;
dc.functest();
// 模板参数范围上的特化版本
TC<int *> dx;
dx.functest();
system("pause");
return 0;
}
局部特化,特化完了之后它本质上还是一个模板;
全特化,特化完了之后就等于一个具体的类;
二、函数模板特化
1、函数模板全特化
#include <iostream>
#include <string>
using namespace std;
// 函数模板泛化版本
template <typename T,typename U>
void tfunc(T &tmprv, U &tmprv2)
{
cout << "tfunc泛化版本!" << endl;
cout << tmprv << endl;
cout << tmprv2 << endl;
}
// 函数模板全特化版本 T =int ,U = double
template <>
void tfunc(int &tmprv, double &tmprv2)
{
cout << "tfunc特化版本!<int, double>" << endl;
cout << tmprv << endl;
cout << tmprv2 << endl;
}
// 函数模板重载函数
void tfunc(int &tmprv, double &tmprv2)
{
cout << "tfunc重载函数版本" << endl;
cout << tmprv << endl;
cout << tmprv2 << endl;
}
int main()
{
const char *p = "I Love China!";
int i = 12;
// 泛化版本
tfunc(p, i);
// 特化版本
int x = 1; double y = 3;
tfunc(x, y);
//编译器选择最合适的版本:普通函数 > 特化版本 > 泛化版本;
system("pause");
return 0;
}
2、函数模板偏特化
函数模板不存在偏特化;
三、模板特化版本放置位置建议
模板的定义与实现都放在.h文件中;
模板的特化版本与泛化版本都应该放在同一个.h文件中,文件的前面放泛化版本,后面放特化本本;