目录
非类型模版参数
模版的特化
函数模版特化
类模版特化
全特化
半特化(偏特化)
参数更进一步的限制
非类型模版参数
在之前学过的例子来看,我们使用模版,它们的参数都是类型模版,根据类型来决定实例化
而模版其实还有一种参数,叫做 非类型模版参数
//非类型模版参数 --- 常量
template<typename T, size_t N>
class array
{
private:
T _arr[N];
};
int main()
{
int a = 10;
const int i = 10;
fjz::array<int, a> arr1; //a是变量,编译会报错
fjz::array<int, i> arr2;
fjz::array<int, 10> arr3;
}
非类型模版参数,它是一个常量,所以如果要传参,也必须只能传一个常量,传变量会报错!!
模版的特化
C++支持了模版之后,给我们写代码带了了很大的便利,而模版的特化,更是近一步优化了模版的特点!
看这样一种场景
template<typename T>
bool less(T v1, T v2)
{
return v1 < v2;
}
int main()
{
int i1 = 5;
int i2 = 4;
int* p1 = &i1;
int* p2 = &i2;
cout << fjz::less<int>(i1, i2) << endl;
cout << fjz::less<int*>(p1, p2) << endl;
cout << endl;
}
如果我们不是想比较指针的大小,而是想比较指针解引用的数据的大小,那么遇上这种情况怎么办? 使用函数模版特化或者是类模版特化
函数模版特化
template<typename T>
bool less(T v1, T v2)
{
return v1 < v2;
}
//函数模版特化格式
template<>
bool less<int*>(int* v1, int* v2)
{
return *v1 < *v2;
}
这时我们就可以对于int* 这一类型进行专门的特化,一旦是发现T类型是int*,就会使用特化版本!
类模版特化
类模板的特化相对于函数模版的特化,多了几种特化形式,适用于不同的场景,更加灵活!
全特化
类模版的全特化与函数模版特化一样
//原模版
template<typename T1, typename T2>
class A {
public:
void func(T1 t1, T2 t2)
{
std::cout << "class A" << std::endl;
}
};
//全特化
template<>
class A<int, char> {
public:
void func(int t1,char t2)
{
std::cout << "class A<int, char>" << std::endl;
}
};
int main()
{
A<int, int>().func();
A<int, char>().func();
return 0;
}
对于模版参数类型的不同,遇到特化相匹配的类型,会优先匹配优化版本的模版类。
半特化(偏特化)
顾名思义,只特化模版参数的某些参数,一些参数不进行特化。
//原模版
template<typename T1, typename T2>
class A {
public:
void func()
{
std::cout << "class A" << std::endl;
}
};
//全特化
template<>
class A<int, char> {
public:
void func()
{
std::cout << "class A<int, char>" << std::endl;
}
};
//半特化(偏特化)
template<typename T1>
class A<T1, char> {
public:
void func()
{
std::cout << "class A<T1, char>" << std::endl;
}
};
int main()
{
A<int, int>().func();
A<int, char>().func();
A<char, char>().func();
return 0;
}
编译器会匹配 类型最为匹配的版本。
参数更进一步的限制
还有一种更为特别的特化,针对指针和引用
//原模版
template<typename T1, typename T2>
class A {
public:
void func()
{
std::cout << "class A" << std::endl;
}
};
//还有一种特化方式,专门特化指针和引用
template<typename T1, typename T2>
class A<T1*, T2*>
{
public:
void func()
{
std::cout << "class A<T1*, T2*>" << std::endl;
}
};
template<typename T1, typename T2>
class A<T1&, T2&>
{
public:
void func()
{
std::cout << "class A<T1&, T2&>" << std::endl;
}
};
template<typename T1, typename T2>
class A<T1*, T2&>
{
public:
void func()
{
std::cout << "class A<T1*, T2&>" << std::endl;
}
};
template<typename T1, typename T2>
class A<T1, T2&>
{
public:
void func()
{
std::cout << "class A<T1, T2&>" << std::endl;
}
};
int main()
{
A<int, int>().func();
A<int, char>().func();
A<char, char>().func();
A<int*, int*>().func();
A<char&, char&>().func();
A<char*, char&>().func();
A<char, char&>().func();
return 0;
}
编译器会匹配 类型最为匹配的版本。