STL template entry to proficiency

Posted by rbarnett on Mon, 16 Sep 2019 13:53:02 +0200

I. What is STL

STL is the abbreviation of Standard Template Library, the Chinese name standard template library, and the general name of a series of software developed by HP Labs. STL is a collection of containers designed to standardize components. STL is now part of C++, so no additional library files need to be installed.

Template template

Function: Write more abstract classes and functions by taking types as parameters.
Originally, in order to achieve a consistent function, we need to constantly overload the function, but under the function of template library, generic programming only needs to provide a function.

1. Function Template

Procedures before using templates:

#include <iostream>
#include <cstring>
using namespace std;

char mymax(char a,char b){
	cout << "char " << endl;
	return a>b?a:b;	
}

int mymax(int a,int b){
	cout << "int " << endl;
	return a>b?a:b;	
}

double mymax(double a,double b){
	cout << "double " << endl;
	return a>b?a:b;	
}

const char *mymax(const char* a,const char* b){
	//return a>b?a:b;	
	return strcmp(a,b)>0?a:b;
}
int main(){
	mymax('a','b');
	mymax(1,3);
	mymax(1.2,3.4);
	short a=1,b=2;
	mymax(a,b);
	mymax("hello","world");
	//mymax(1,2.34);//mymax(int,double) --> mymax(int,int)  mymax(double,double)
	return 0;	
}

After using the template, the program:

#include <iostream>
#include <typeinfo>
#include <cstring>
using namespace std;

//Function Template Generic Programming
template<typename T>
T mymax(T a,T b){
	cout << typeid(T).name() << endl;
	return a>b?a:b;	
}

//Special version of functions
template<>
const char* mymax<const char*>(const char* a,const char* b){
	cout << "const char*" << endl;
	return strcmp(a,b)>0?a:b;
}

int main(){
	cout << mymax<int>(1,3) << endl;
	cout << mymax<double>(3.14,2.39) << endl;
	cout << mymax<char>('a','b') << endl;
	cout << mymax<double>('a','b') << endl;
	cout << mymax<const char*>("hello","world") << endl;	
	return 0;	
}

Specific function versions are required for specific types, otherwise matching functions will not be found during compilation.
Find the maximum in an array:

#include <iostream>
#include <cstring>
using namespace std;

template<typename K>
K maxOfArr(K arr[],size_t len){
	K m = arr[0];
	for(size_t i=0;i<len;i++){
		if(m < arr[i]){
			m = arr[i];	
		}	
	}
	return m;
}
//Special version of functions
template<>
const char* maxOfArr<const char*>(const char* arr[],size_t len){
	const char *m = arr[0];
	for(int i=0;i<len;i++){
		if(strcmp(m,arr[i])<0){
			m = arr[i];	
		}	
	}
	return m;
}

int main(){
	int arr[3] = {1,3,2};
	cout << maxOfArr<int>(arr,3) << endl;
	double brr[4] = {1,2.3,3.2,2.7};
	cout << maxOfArr<double>(brr,4) << endl;
	const char * crr[5] = {"zhaoyun","guanyu","machao","huangzhong","zhangfei"};
	cout << maxOfArr<const char*>(crr,5) << endl;
	cout << maxOfArr(arr,3) << endl;
	cout << maxOfArr(brr,4) << endl;
	cout << maxOfArr(crr,5) << endl;
	return 0;	
}

2. Class Template

Take the implementation of the stack as an example:

#include <iostream>
#include <cstring>
using namespace std;

template<typename K>
K maxOfArr(K arr[],size_t len){
	K m = arr[0];
	for(size_t i=0;i<len;i++){
		if(m < arr[i]){
			m = arr[i];	
		}	
	}
	return m;
}
template<>
const char* maxOfArr<const char*>(const char* arr[],size_t len){
	const char *m = arr[0];
	for(int i=0;i<len;i++){
		if(strcmp(m,arr[i])<0){
			m = arr[i];	
		}	
	}
	return m;
}

int main(){
	int arr[3] = {1,3,2};
	cout << maxOfArr<int>(arr,3) << endl;
	double brr[4] = {1,2.3,3.2,2.7};
	cout << maxOfArr<double>(brr,4) << endl;

	const char * crr[5] = {"zhaoyun","guanyu","machao","huangzhong","zhangfei"};
	cout << maxOfArr<const char*>(crr,5) << endl;
	cout << maxOfArr(arr,3) << endl;
	cout << maxOfArr(brr,4) << endl;
	cout << maxOfArr(crr,5) << endl;
	return 0;	
}

Full specialization: Although the function logic is the same, it needs to rewrite all the functions in the class.

#include <iostream>
#include <cstring>
using namespace std;

template<typename T>
class Max{
public:
	void show(){
		cout << a << " : " << b << endl;	
	}
	Max(T a,T b):a(a),b(b){
		cout << "T" << endl;	
	}
	T max(){
		return a>b?a:b;	
	}
	T min(){
		return a>b?b:a;	
	}	
private:
	T a;
	T b;
};

//special version
template<>
class Max<const char *>{
public:
	Max(const char* a,const char *b):a(a),b(b){
		cout << "const char*" << endl;	
	}
	
	void show(){
		cout << a << " : " << b << endl;	
	}
	
	const char *max(){
		return strcmp(a,b)>0?a:b;	
	}
	const char *min(){
		return strcmp(a,b)>0?b:a;
	}
private:
	const char* a;
	const char* b;
};

int main(){
	Max<int> m1(1,3);
	cout << m1.max() << endl;
	Max<double> m2(2.3,2.1);
	cout << m2.min() << endl;

	Max<const char*> m3("Hello","World");
	cout << m3.max() << endl;
	m3.show();
	return 0;	
}

Membership specialization: only a special version of the member function is needed;

#include <iostream>
#include <cstring>
using namespace std;

template<typename T>
class Max{
public:
	void show(){
		cout << a << " : " << b << endl;	
	}
	Max(T a,T b):a(a),b(b){
		cout << "T" << endl;	
	}
/*
	template <const char*>
	const char *max(){
		cout << "Membership specialization version "<< endl;
		return strcmp(a,b)>0?a:b;	
	}
*/
	T max(){
		return a>b?a:b;	
	}
	//Specialized versions of declaration Members
	template <const char *>
	const char *max();
	T min(){
		cout << "Membership functions in non-materialized versions" << endl;
		return a>b?b:a;	
	}
	//Specialized versions of declaration Members
	template <const char*>
	const char *min();
	/*
	{
		cout << "Membership specialization version "<< endl;
		return strcmp(a,b)>0?b:a;	
	}
	*/
private:
	T a;
	T b;
};
//Functions in the Specialized Version of Membership Functions
//It is not effective to implement outside class and inside class!!!
template<>
const char * Max<const char*>::max(){
	cout << "Membership specialization version" << endl;
	return strcmp(a,b)>0?a:b;	
}
template<>
const char * Max<const char*>::min(){
	cout << "Membership specialization version" << endl;
	return strcmp(a,b)>0?b:a;
}
//No longer rewrite all functions in a class
/*
template<>
class Max<const char *>{
public:
	Max(const char* a,const char *b):a(a),b(b){
		cout << "const char*" << endl;	
	}
	
	void show(){
		cout << a << " : " << b << endl;	
	}
	
	const char *max(){
		return strcmp(a,b)>0?a:b;	
	}
	const char *min(){
		return strcmp(a,b)>0?b:a;
	}
private:
	const char* a;
	const char* b;
};
*/

int main(){
	Max<int> m1(1,3);
	cout << m1.max() << endl;
	Max<double> m2(2.3,2.1);
	cout << m2.min() << endl;

	Max<const char*> m3("Hello","World");
	cout << m3.max() << endl;
	cout << m3.min() << endl;
	
	m3.show();

	return 0;	
}

Partialization: Select the appropriate class template according to the level of the specialization program; only the class has, function partialization is actually overloading;

#include <iostream>
using namespace std;

template<typename T,typename K,typename L>
class A{
public:
	void show(){
		cout << "<T,K,L>" << endl;
	}
};

//partial specialization
template<typename T,typename K>
class A<T,K,K>{
public:
	void show(){
		cout << "<T,K,K>" << endl;
	}	
};

template<typename T>
class A<T,T,T>{
public:
	void show(){
		cout << "<T,T,T>" << endl;	
	}
};

template<typename T>
class A<T,T*,T*>{
public:
	void show(){
		cout << "<T,T*,T*>" << endl;	
	}
};
template<typename T>
class A<T,T[],T[]>{
public:
	void show(){
		cout << "<T,T[],T[]>" << endl;
	}
};

int main(){
	//Select the appropriate class template to instantiate according to the level of the Specialization program
	A<int,float,double> a;
	a.show();
	A<int,double,double> b;
	b.show();
	A<int,int,int> c;
	c.show();
	//Pointer Partialization TKK T*T*
	A<int,int*,int*> d;
	d.show();
	//Partialization of arrays T [] T []
	A<int,int[],int[]> e;
	e.show();
	return 0;	
}

Topics: Programming