non-type template parameters
Template parameters classify type parameters to non-type parameters.
The type parameter is: appearing in the template parameter list, followed by the parameter type name such as class or typename.
A non-type parameter is to use a constant as a parameter of a class (function) template, and the parameter can be used as a constant in the class (function) template. (Non-type parameters can only be integers)
#include<iostream> #include <array> #include <string> using namespace std; // static array // non-type template parameter -- constant template<class T, size_t N> class Array { private: T _a[N]; }; int main() { Array<int, 10> a1; Array<int, 100> a2; return 0; }
The above is a static array encapsulated by a class.
Notice:
1. Floating point numbers, class objects, and strings are not allowed as non-type template parameters.
2. Non-type template parameters must be able to confirm the result at compile time.
template specialization
Usually, templates can be used to implement some type-independent codes, but for some special types, some wrong results may be obtained and special handling is required.
For example: implement a function template specially used for less than comparison
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; // can be compared, the result is correct Date d1(2022, 7, 7); Date d2(2022, 7, 8); cout << Less(d1, d2) << endl; // can be compared, the result is correct Date* p1 = &d1; Date* p2 = &d2; cout << Less(p1, p2) << endl; // can be compared, the result is wrong return 0; }
Add the following code:
// Specialize Less function templates template<> bool Less<Date*>(Date* left, Date* right) { return *left < *right; }
The result is correct.
Note: In general, if the function template encounters a type that cannot be processed or is processed incorrectly, the function is usually given directly for simplicity of implementation.
class template specialization
full specialization
Full specialization is to determinize all the parameters in the template parameter list.
partial specialization
Partial specialization: Any specialization that further conditionally restricts the design of template parameters.
There are two types of partial specialization:
1. Partial specialization: Specialize part of the parameters in the template parameter class table.
2. Further restrictions on parameters: Partial specialization does not just refer to specialization of some parameters, but a specialized version designed for further conditional restrictions on template parameters.
class template specialization
template<class T1,class T2> class A { public: A() { cout << "A:T1 T2" << endl; } }; //full specialization template<> class A<char, int> { public: A() { cout << "A:char int(full specialization)" << endl; } }; //partial specialization - partial specialization template<class T> class A<char, T> { public: A() { cout << "A:char T(partial specialization)" << endl; } }; //Partial specialization - further restrictions on parameters template<class T1, class T2> class A<T1*, T2*> { public: A() { cout << "A:char int(Restrict parameter type to pointer)" << endl; } }; template<class T1, class T2> class A<T1&, T2&> { public: A() { cout << "A:char int(Restrict parameter type to reference)" << 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; }