[C++] - template preliminary level

catalogue

1, Concept

2, Classification of templates

2.1 function template

2.1.1 function template format

2.1.2 principle of function template

2.1.3 instantiation of function template

2.1.4 matching principle of template parameters

Type 2.2 formwork

2.2.1 definition format of class template

2.2.2 instantiation of class template

1, Concept

First, let's take a look at how we implement two integer data exchanges, two character data exchanges and two floating-point data exchanges in C++

void Swap(int& x1, int& x2)
{
	int x = x1;
	x1 = x2;
	x2 = x;
}

void Swap(char& x1, char& x2)
{
	char x = x1;
	x1 = x2;
	x2 = x;
}

void Swap(double& x1, double& x2)
{
	double x = x1;
	x1 = x2;
	x2 = x;
}

int main()
{
	int a1 = 10, a2 = 20;
	char c1 = 'a', c2 = 'b';
	double d1 = 10.1, d2 = 20.1;

	cout << a1 << ' ' << a2 << endl;
	cout << c1 << ' ' << c2 << endl;
	cout << d1 << ' ' << d2 << endl;

	Swap(a1, a2);
	Swap(c1, c2);
	Swap(d1, d2);

	cout << a1 << ' ' << a2 << endl;
	cout << c1 << ' ' << c2 << endl;
	cout << d1 << ' ' << d2 << endl;
	return 0;
}

The above can be realized by function overloading, but the following problems exist:

        1. Overloaded functions only have different types, and the code reuse rate is relatively low. As long as new types appear, corresponding functions need to be added;
        2. The maintainability of the code is relatively low. An error may cause all overloads to fail;

Can you tell the compiler a template to generate code according to different types?

C++ introduces templates. What is a template? It can be understood as movable type printing. In ancient times, if you wanted to spread poetry widely, the ancients could do a lot of copying by manpower, but it was time-consuming and laborious; So the ancients thought of using a board to engrave these words and directly print them on white paper, which not only improved the efficiency, but also the handwriting was identical; Very practical;

The same is true for C++ templates. In each function, the function name is the same, the return value is the same, the function is the same, but the type is different; So the difference of this type is not equivalent to what color of words you want to print. Take pouring in modern machinery industry as an example:

The above also shows that C language does not support generic programming;

2, Classification of templates

There are two types of templates in C++: function templates and class templates

2.1 function template

A function template represents a function family. The function template is independent of type and is parameterized when used. A specific type version of a function is generated according to the actual parameter type.

2.1.1 function template format

template<class T>//T here is

//Here, class T can also be written as typename T
//T is the name of the template, which can be modified

void Swap( T& left, T& right) //In this function, the type becomes T, and its type depends on the argument
{
     T temp = left;
     left = right;
     right = temp; 
}

2.1.2 principle of function template

A function template is a blueprint. It is not a function itself. It is a mold for the compiler to generate specific types of functions in a specific way. So in fact, the template is to give the compiler the duplicate things that we should have done

 

In the compiler compilation stage, for the use of template functions, the compiler needs to deduce and generate functions of corresponding types according to the input argument types for calling. For example, when a function template is used with the double type, the compiler determines T as the double type by deducting the actual parameter type, and then generates a code specifically dealing with the double type, which is the same for the character type.
template <class T>

void Swap(T& x1, T& x2)
{
	T x = x1;
	x1 = x2;
	x2 = x;
}
int main()
{
	int a = 0, b = 1;
	char c = 'a', d = 'd';
	cout << a << b << c << d << endl;

	Swap(a, b);
	Swap(c, d);
	cout << a << b << c << d << endl;

	return 0;
}

2.1.3 instantiation of function template

When a function template is used with different types of parameters, it is called function template instantiation. Template parameter instantiation includes implicit instantiation and explicit instantiation.

① Implicit instantiation -- let the compiler deduce the actual types of template parameters based on the actual parameters

template <class T>
T Add(const T& left, const T& right)
{
	return left + right;
}

int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.1, d2 = 20.2;
	cout << Add(a1, a2) << endl;
	cout << Add(d1, d2) << endl;

	return 0;
}

Note: you cannot pass different types of parameters into a function template.

During compilation, when the compiler sees the instantiation, it needs to deduce its parameter type, deduce T to int through argument a1, and deduce T to double through argument d1. However, there is only one T in the template parameter list. The compiler cannot determine whether T should be determined as int or double, and an error is reported
Note: in the template, the compiler generally does not perform type conversion, because once the conversion fails, the compiler will be blamed
Add(a1, d2);

//Use cast
Add(a1, (int)d2);

② Display instantiation -- specify the actual type of the template parameter in the < > after the function name

In the above code, in addition to forced type conversion, display instantiation can also be used to solve the problem of parameter transmission of different parameters;  

//Use display instantiation
Add<int>(a1, d2);
Add<double>(a1, d2);

2.1.4 matching principle of template parameters

1. a non template function can exist simultaneously with a function template with the same name, and the function template can also be instantiated as the non template function;
//Addition function specialized in int
int Add(int left, int right)
{
	return left + right;
}

//General addition function
template<class T1,class T2>
T1 Add(T1 left, T2 right)
{
	return left + right;
}

int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.1, d2 = 20.2;

	cout << Add(a1, a2) << endl;//When a function template and a common function appear at the same time, it will call the common function first

	cout << Add(d1, d2) << endl;

	return 0;
}
For non template functions and function templates with the same name, if other conditions are the same, non template functions will be called preferentially during transfer without generating an instance from the template. If the template can produce a function with a better match, the template will be selected;  
emphasize : template functions do not allow automatic type conversion, but ordinary functions can perform automatic type conversion

Type 2.2 formwork

2.2.1 definition format of class template

template<class T1, class T2, ..., class Tn>
class Class template name
{
 // Intra class member definition
};
When we want to use the stack to store different types, we often use the type (int, char...) typedef, but in the same program, when you want to store int in the first stack created and char in the second stack created, you can't do it; Class templates are introduced for this kind of strong C++.
template <class T>
class Stack
{
public:
	Stack(int capacity = 4)
		:_top(0)
		, _capacity(capacity)
	{
		_a = new T[capacity];
	}

	void Push(const T& x);

	~Stack()
	{
		delete[] _a;
		_a = nullptr;
		_capacity = _top = 0;
	}
private:
	T* _a;
	int _top;
	int _capacity;
};


template <class T>//Class member functions are declared in the class. When they are defined outside the class, a template parameter list needs to be added
void Stack<T>::Push(const T& x)
{
	/********/
}

int main()
{
    // Stack--- class name
    // Stack<int> etc. - type
	Stack<int> st1;    //Store int
	Stack<double> st2; //Store double
	Stack<char> st3;   //Store char
	return 0;
}

2.2.2 instantiation of class template

Class template instantiation (in the main function) is different from function template instantiation. Class template instantiation needs to follow the class template name with < >, and then put the instantiated type in < >. The class template name is not a real class, but the instantiation result is a real class.

// Stack class name. Stack<int>, stack<double>, and stack<char> are the types
Stack<int> st1; 
Stack<double> st2; 
Stack<char> st3;   

Tags: C++ linq p2p

Posted by poppy on Wed, 01 Jun 2022 10:00:01 +0530