Advanced templates (including specializations)

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;
}

 

Tags: Algorithm C++ data structure

Posted by scarabee on Sat, 11 Feb 2023 21:32:42 +0530