[C++] Specialization of templates

1. Concept

Under normal circumstances, using templates can achieve some type-independent code, but for some special types, you may get some wrong results, such as:

template<class T>
bool IsEqual(T& left,T& right)
{
    
    
	return left == right;
}

void Test()
{
    
    
	char* p1 = "hello";
	char* p2 = "world";
	if(IsEqual(p1,p2)
		cout<<p1<<endl;
	else
		cout<<p2<<endl;
}

At this point, you need to specialize the template. That is: on the basis of the original template class, a special implementation method for a special type. Template specialization is divided into function template specialization and class template specialization .

2. Function template specialization

The specialization steps of the function template :
1. There must be a basic function template first
. 2. The keyword template is followed by a pair of empty angle brackets <>
3. The function name is followed by a pair of angle brackets, and the angle brackets specify that specialization is required type
4. function parameter list: parameter types must be the foundation and template functions exactly the same, if different compilers may report some strange errors.

The above code is transformed into:

template<>
bool IsEqual<char*>(char*& left,char*&right)
{
    
    
	if(strcmp(left,right)>0)
		return true;
	return false;

Note: In general, if a function template encounters a type that cannot be processed or is processed incorrectly, the function is usually given directly for simple implementation, such as:

bool IsEqual(char* left,char* right)
{
    
    
	if(strcmp(left,right) > 0)
		return true;
	return false;
}

3. Class template specialization

3.1 All specialization

Full specialization is to determine all the parameters in the template parameter list.

template<>
class Data < int, char >
{
    
    
public:
	Data(){
    
     cout << "Data<int,char>" << endl; }
private:
	int _d1;
	char _d2;
};

3.2 Biased specialization

Partial specialization: any specialization version that further restricts the design of the template parameters.

3.2.1 Partial specialization

Specialize part of the parameters in the template parameter class table.

template<class T>
class Data < T, int >
{
    
    
public:
	Data(){
    
     cout << "Data<T,int>" << endl; }
private:
	T _d1;
	int _d2;
};

3.2.2 Further restrictions on parameters

Partial specialization does not only refer to specialization of some parameters, but a specialization version designed for further conditional restrictions on template parameters.

template<class T1,class T2>
class Data < T1*, T2* >
{
    
    
public:
	Data(){
    
     cout << "Data<T1*,T2*>" << endl; }
private:
	T1* _d1;
	T2* _d2;
};

3.3 Application of Class Template Specialization—Type Extraction

Custom type element:

String s1[] = {
    
    "1111","2222","3333"};
String s2[3];

Suppose we want to copy the contents of s1 to s2, the first method we want to use memcpy to achieve:
Insert picture description here
memcpy is copied in the form of bytes, copying the contents of one memory intact to another memory In this way, the original content in s2 cannot be found, and there is a memory leak problem.
The second method is to use a for loop, but this method is too cumbersome for built-in type elements. So how do you distinguish between built-in type elements and custom type elements to copy? At this time, type extraction is used .
code show as below:

//表示内置类型
struct True
{
    
    
	static bool Get()
	{
    
    
		return true;
	}
};

//表示自定义类型
struct False
{
    
    
	static bool Get()
	{
    
    
		return false;
	}
};

//用该类模板来检测T到底是什么类型---自定义类型
template<class T>
struct TypeTraits
{
    
    
	typedef False PODTYPE;
};

//所有内置类型全部进行特化
template<>
struct TypeTraits < int >
{
    
    
	typedef True PODTYPE;
};

template<>
struct TypeTraits < char >
{
    
    
	typedef True PODTYPE;
};

template<>
struct TypeTraits < double >
{
    
    
	typedef True PODTYPE;
};
//...

template<class T>
void Copy(T* dst, const T* src, size_t size)
{
    
    
	if (TypeTraits<T>::PODTYPE::Get())
	{
    
    
		//如果是内置类型元素之间的拷贝
		memcpy(dst, src, sizeof(T)*size);
	}
	else
	{
    
    
		//如果是自定义类型元素之间的拷贝
		for (size_t i = 0; i < size; ++i)
			dst[i] = src[i];
	}
}

void TestCopy()
{
    
    
	int array1[] = {
    
     1, 2, 3, 4, 5 };
	int array2[5];
	Copy(array2, array1, sizeof(array1) / sizeof(array1[0]));

	String s1[] = {
    
     "1111", "2222", "3333" };
	String s2[3];
	Copy(s2, s1, 3);
}

Guess you like

Origin blog.csdn.net/zhao_leilei/article/details/109766354