非类型模板参数
模板参数分类类型形参与非类型形参。
类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。(非类型参数只能是整型)
#include<iostream>
#include <array>
#include <string>
using namespace std;
// 静态数组
// 非类型模板参数 -- 常量
template<class T, size_t N>
class Array
{
private:
T _a[N];
};
int main()
{
Array<int, 10> a1;
Array<int, 100> a2;
return 0;
}
以上是利用类封装的静态数组。
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
2. 非类型的模板参数必须在编译期就能确认结果。
模板的特化
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结 果,需要特殊处理,
比如:实现了一个专门用来进行小于比较的函数模板
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
bool operator<(const Date& d)const
{
return (_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day);
}
bool operator>(const Date& d)const
{
return (_year > d._year) ||
(_year == d._year && _month > d._month) ||
(_year == d._year && _month == d._month && _day > d._day);
}
friend ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
private:
int _year;
int _month;
int _day;
};
template<class T>
bool Less(T left, T right)
{
return left < right;
}
int main()
{
cout << Less(1, 2) << endl; // 可以比较,结果正确
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less(d1, d2) << endl; // 可以比较,结果正确
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; // 可以比较,结果错误
return 0;
}
加入以下代码:
// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
return *left < *right;
}
结果正确。
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出。
类模板特化
全特化
全特化即是将模板参数列表中所有的参数都确定化。
偏特化
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。
偏特化有以下两种表现方式:
一、部分特化: 将模板参数类表中的一部分参数特化。
二、参数更进一步的限制: 偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版 本。
类模板特化实现
template<class T1,class T2>
class A
{
public:
A()
{
cout << "A:T1 T2" << endl;
}
};
//全特化
template<>
class A<char, int>
{
public:
A()
{
cout << "A:char int(全特化)" << endl;
}
};
//偏特化——部分特化
template<class T>
class A<char, T>
{
public:
A()
{
cout << "A:char T(偏特化)" << endl;
}
};
//偏特化——对参数的进一步限制
template<class T1, class T2>
class A<T1*, T2*>
{
public:
A()
{
cout << "A:char int(限制参数类型为指针)" << endl;
}
};
template<class T1, class T2>
class A<T1&, T2&>
{
public:
A()
{
cout << "A:char int(限制参数类型为引用)" << endl;
}
};
int main()
{
A<int, int> a1;
A<char, int> a2;
A<char, char> a3;
A<int*, int*> a4;
A<int&, int&> a5;
return 0;
}