C++类模板的特化
有的时候某些类型不能直接用来实例化类模板,或者说直接实例化不能满足需要,
此时就要针对这种类型进行特化,包括特化(即全特化)和偏特化。
1、特化为绝对类型
目的:为了针对特殊的类型进行特殊处理,重新修改成新的逻辑,定义一个
新的特化的类模板。
特点:template后没有形参说明,类模板名加了模板实参列表。
基本语法:
template<>
class 类模板名<模板实参列表>
{
新的逻辑操作
};
2、偏特化(部分特化)
给出部分实参。仍有个别参数没有给出实际参数。
特点:template后的模板形参的形参没有全部不写,类模板名后添加了参数说明。
或者两个都
基本语法:
template<模板形参列表>
class 类模板名<模板形参表>
{
};
注:类模板名后的形参,可以把template后的形参当作已知的类型,组合成新
的类型来作为类模板的参数。然后通过实例化template的形参,
最后进一步确定类模板的实参。
注:所有特化类模板之前,一定先需要定义同名的非特化类模板,否则会有编译错误
注:所有特化模板的形参以跟着类模板名后面的 < >为标准,而非特化模板以跟着
template后面的< >为标准。进行参数赋值。
一、全特化
测试程序
#include <iostream>
using namespace std;
//类模板的特化之全特化
//普通非特化类模板
template <typename T,int size>
class Vector
{
private :
T arr_data[size];
public:
Vector(T *data)
{
for(int i=0;i<size;i++)
{
arr_data[i] = *(data+i);
}
}
T Sum();
};
template <typename T,int size>
T Vector<T,size>::Sum()
{
cout<<"调用非特化类模板实例的Sum函数!"<<endl;
T sumvalue=0;
for(int i=0;i<size;i++)
{
sumvalue+=*(arr_data+i);
}
return sumvalue;
}
//全特化类模板
template <>
class Vector<int,1>
{
private:
int data;
public:
Vector(int d);
int Sum();
};
//全特化的函数在在类外定义,不需要加上 template < >
Vector<int,1>::Vector(int d):data(d)
{
}
int Vector<int,1>::Sum()
{
cout<<"调用全特化类模板Vector<int,1>的函数Sum"<<endl;
return data;
}
int main()
{
int int_arry[10]={1,2,3,4,5,6,7,8,9,10};
float float_arry[10]={2,3,4,5,6,7,8,9,10,11.0};
int i1=100;
Vector<int,10> int_vector(int_arry);
Vector<float ,10> float_vector(float_arry);
Vector<int,1> int1(i1);
cout<<int_vector.Sum()<<endl;
cout<<float_vector.Sum()<<endl;
cout<<int1.Sum()<<endl;
return 0;
}
输出结果:
调用非特化类模板实例的Sum函数!
55
调用非特化类模板实例的Sum函数!
65
调用全特化类模板Vector<int,1>的函数Sum
100
Process returned 0 (0x0) execution time : 0.130 s
Press any key to continue.
二、部分特化之普通特化
测试程序:
#include <iostream>
#include <cstring>
using namespace std;
//类模板的特化
//普通的非特化类模板
template <typename T,int size>
class Vector
{
private:
T arr_data[size];
public:
Vector(T *data )
{
for(int i=0;i<size;i++)
{
arr_data[i]=data[i];
}
}
T Sum();
};
template <typename T,int size>
T Vector<T,size>::Sum()
{
T sumvalue=0;
cout<<"调用非特化类模板实例中的函数!"<<endl;
for(int i=0;i<size;i++)
{
sumvalue+=arr_data[i];
}
return sumvalue;
}
//这样的求和,如果是针对INT float型都适合,可是针对字符数组就不行。
//普通的部分特化
template <int size> //只有一个参数被给了实参。
class Vector<char ,size>
{
private:
char arr_data[size+1];
public:
Vector(char *data )
{
strcpy(arr_data,data);
}
char * Sum();
};
template <int size>
char * Vector<char,size>::Sum()
{
cout<<"调用部分特化类模板Vector<char,size>中的sum函数!"<<endl;
char * c_arry=new char[size+1];
strcpy(c_arry,arr_data);
return c_arry;
}
int main()
{
int int_array[10]={1,2,3,4,5,6,7,8,9,10};
float float_array[10]={2,3,4,5,6,7,8,9,10.0,11.0};
char c_array[10]="ABCDEFG";
const int c_size=sizeof(c_array); //这里如果使用strlen就不可以出现在模板实参中,因为sizeof()编译时处理的。strlen是函数,运行时决定,
//int size 实参要求必须是编译时就能决定出来的常量表达式
Vector<int,10> int_vector(int_array);
Vector<float,10> float_vector(float_array);
Vector<char,c_size> char_vector(c_array);//这里的实例化,也必须是两个参数,
cout<<int_vector.Sum()<<endl;
cout<<float_vector.Sum()<<endl;
cout<<char_vector.Sum()<<endl;
return 0;
}
输出结果:
调用非特化类模板实例中的函数!
55
调用非特化类模板实例中的函数!
65
调用部分特化类模板Vector<char,size>中的sum函数!
ABCDEFG
三、部分特化之引用与指针
测试程序:
#include <iostream>
using namespace std;
//类模板的特化
template <typename T,typename U>
class Ctest
{
public:
void f();
};
template <typename T,typename U>
void Ctest<T,U>::f()
{
cout<<"调用非特化类模板实例对象的函数"<<endl;
}
//偏特化为引用
template <typename T,typename U>
class Ctest<T &,U &>
{
public:
void f();
};
template <typename T,typename U>
void Ctest<T &,U &>::f()
{
cout<<"调用偏特化为引用的类模板实例对象的函数"<<endl;
}
//偏特化为指针 第二个参数是int
template <typename T>
class Ctest<T *,int>
{
public:
void f();
};
template <typename T>
void Ctest<T *,int>::f()
{
cout<<"调用偏特化为指针,第二个参数是int的类模板实例对象的函数"<<endl;
}
int main()
{
//只用完全符合特化模板形参的才会调用特化模板,只要不符合的调用的全都是非特化模板。
Ctest<int,int> in_c;
in_c.f();
Ctest<int &,int &> in_c1;
in_c1.f();
Ctest<int *,int &> in_c2;
in_c2.f();
Ctest<int *,int> in_c3;
in_c3.f();
return 0;
}
输出结果:
调用非特化类模板实例对象的函数
调用偏特化为引用的类模板实例对象的函数
调用非特化类模板实例对象的函数
调用偏特化为指针,第二个参数是int的类模板实例对象的函数
Process returned 0 (0x0) execution time : 1.451 s
Press any key to continue.
四、部分特化之类模板
测试程序:
Vector.h
#include <iostream>
using namespace std;
//类模板的特化之全特化
//普通非特化类模板
template <typename T,int size>
class Vector
{
private :
T arr_data[size];
public:
Vector(T *data)
{
for(int i=0;i<size;i++)
{
arr_data[i] = *(data+i);
}
}
T Sum();
};
template <typename T,int size>
T Vector<T,size>::Sum()
{
cout<<"Vector调用非特化类模板实例的Sum函数!"<<endl;
T sumvalue=0;
for(int i=0;i<size;i++)
{
sumvalue+=*(arr_data+i);
}
return sumvalue;
}
//全特化类模板
template <>
class Vector<int,1>
{
private:
int data;
public:
Vector(int d);
int Sum();
};
//全特化的函数在在类外定义,不需要加上 template < >
Vector<int,1>::Vector(int d):data(d)
{
}
int Vector<int,1>::Sum()
{
cout<<"Vector调用全特化类模板Vector<int,1>的函数Sum"<<endl;
return data;
}
main.cpp
#include <iostream>
#include "Vector.h"//包含我们自定义的类模板头文件
using namespace std;
//类模板的特化之特化为另一个类模板
template <typename T,int size>
class Ctest
{
public:
void f();
};
template <typename T,int size>
void Ctest<T,size>::f()
{
cout<<"Ctest调用非特化类模板实例对象的函数"<<endl;
}
template <typename T,int size>
class Ctest< Vector<T,size>,size>
{
public:
void f();
};
template <typename T,int size>
void Ctest<Vector<T,size>,size>::f()
{
cout<<"Ctest调用特化为Vector类模板的函数"<<endl;
}
int main()
{
//Vector的参数我们并不关心特化和非特化,而由Vector.h文件中的内容决定。
//非特化模板 以跟着template后的< 参数列表> 为标准进行参数赋值
Ctest<int,10> c001;
c001.f();
//特化模板 以跟着类模板名后的< 参数列表> 为标准进行参数赋值
Ctest<Vector<int,10>,10> c002;
c002.f();
return 0;
}
输出结果:
Ctest调用非特化类模板实例对象的函数
Ctest调用特化为Vector类模板的函数
Process returned 0 (0x0) execution time : 1.685 s
Press any key to continue.