C++——Template Elementary


Foreword:

In this chapter, we will learn templates and formally contact generic programming. C++Compared with Clanguages, there are so many rich interfaces and types, all of which originate from generic programming. STLThe content of this chapter is the initial knowledge of the template, which will lay a solid foundation for the next study.

1. Generic programming

How to implement a general exchange function ( swap)? We have already learned the use of function overloading, and function overloading is very useful in this scenario:

void Swap(int& a, int& b)
{
    
    
	auto tmp = a;
	a = b;
	b = tmp;
}

void Swap(double& a, double& b)
{
    
    
	auto tmp = a;
	a = b;
	b = tmp;
}

void Swap(char& a, char& b)
{
    
    
	auto tmp = a;
	a = b;
	b = tmp;
}
//...

Although it is possible to use function overloading , there are several disadvantages:

  1. The overloaded functions are only of different types, and the code reuse rate is relatively low. As long as a new type appears, the user needs to add the corresponding function
  2. The maintainability of the code is relatively low, one error may cause all overloads to be error

Can you tell the compiler a model and let the compiler use the model to generate code according to different types?

  • This is the template we are going to talk about today - the template is the basis of generic programming . Templates apply not only to functions , but also to classes .

2. Function template

1. The concept of function template

A function template represents a family of functions . The function template has nothing to do with the type . It is parameterized when used, and a specific type version of the function is generated according to the type of the actual parameter.

2. The format of the function template

template<typename T1, typename T2,......,typename TN>
返回值类型 函数名(参数列表)
{
    
    
	//...函数体
}

Example:

template<typename T>
void Swap(T& a,T& b)
{
    
    
	auto tmp = a;
	a = b;
	b = tmp;
}
template<class N>
void Swap(N& a, N& b)
{
    
    
	auto tmp = a;
	a = b;
	b = tmp;
}

Notice:

  1. typenameThe following content does not have to be T, it can be freely specified;
  2. typenameIt is used to define template parameter keywords , and can also be used class(remember: cannot be used structinstead class)

3. The principle of function template

A function template is a process of description, a blueprint, a template , not a real function. The compiler generates concrete type functions in a specific way based on the template . So in fact, the template is to hand over the repetitive things that we should do to the compiler (think about the principle of printing).

insert image description here

In the compiler compilation stage, the compiler needs to deduce and generate a function of the corresponding type according to the type of the incoming actual parameter for calling.

For example: when using a function template with the e type, the compiler will determine the type doublby deducing the type of the actual parameter , and then generate a code that specifically handles the type, and the same is true for the character type.Tdoubledouble

4. Instantiation of function templates

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

(1) Implicit instantiation

Let the compiler deduce the actual type of the template parameter based on the actual parameter.

Example:

template<class T>
T Add(T a, T b)
{
    
    
	return  a + b;
}
void Test()
{
    
    
	int a = 10;
	int b = 100;
	cout << Add(a, b) << endl;
}

insert image description here

(2) Explicit instantiation

Specify the actual type of the template parameter<> in after the function name .

Error example:

template<class T>
T Add(T a, T b)
{
    
    
	return  a + b;
}

void Test()
{
    
    
	int a = 10;
	double d = 3.14;

	cout << Add(a, d) << endl;
}

operation result:

insert image description here

wrong reason:

  • Because during compilation, when the compiler sees the instantiation, it needs to deduce the parameter type from the actual parameter , and the actual parameter awill be deduced into the type, but there is only one template parameter list, the compiler cannot determine whether it should be determined as or the type, and an error is reported.TintdTdoubleTTintdouble

correct way

①Explicit instantiation : It is telling the compiler: You don't need to deduce it, I have already specified this type.

template<class T>
T Add(T a, T b)
{
    
    
	return  a + b;
}

void Test()
{
    
    
	int a = 10;
	double d = 3.14;
	cout << Add<int>(a, d) << endl;
}

insert image description here

② Using multiple template parameters :

template<class T,class Y>
Y Add(T a, Y b)
{
    
    
	return  a + b;
}

void Test()
{
    
    
	int a = 10;
	double d = 3.14;
	cout << Add(a, d) << endl;
}

insert image description here

Notice:

  • In the following case, the function called twice swapis not the same function!
template<class N>
void Swap(N& a, N& b)
{
    
    
	auto tmp = a;
	a = b;
	b = tmp;
}
void Test()
{
    
    
	int a = 10;
	int b = 100;
	Swap(a,b);

	char c1 = 'a';
	char c2 = 'b';
	Swap(c1, c2);
}

The assembly code is shown in the figure below, obviously the function called twice is not a function (one type is Swap< int >, one is Swap< char >). In fact, although we cannot see the code of these two functions, they actually generate:

insert image description here

5. Matching principle of template parameters

①A non-template function can coexist with a function template with the same name , and the function template can also be instantiated as this non-template function .

template<class T>
T Add(T a, T b)
{
    
    
	return  a + b;
}

int Add(int a, int b)
{
    
    
	return a + b;
}

void Test()
{
    
    
	int a = 10;
	int b = 100;
	cout << Add<int>(a, b) << endl;
}

②For a non-template function and a function template with the same name , if other conditions are the same, the non-template function will be called first and an instance will not be generated from the template when mobilizing. If the template can produce a function with a better match , then the template will be chosen .

template<class T,class Y>
Y Add(T a, Y b)
{
    
    
	cout << "模板" << endl;
	return  a + b;
}
int Add(int a, int b)
{
    
    
	cout << "非模板" << endl;
	return a + b;
}
void Test()
{
    
    
	int a = 10;
	int b = 100;
	double d = 3.14;
	cout << Add(a, b) << endl;//使用非模板函数
	cout << Add(a, d) << endl;//使用模板
}

insert image description here

③Template functions do not allow automatic type conversion , but ordinary functions can perform automatic type conversion

3. Class template

1. Definition format of class template

template<class T1, class T2, ..., class Tn>
class 类模板名
{
    
    
	// 类内成员定义
};

Example:

template<class T>
class Stack
{
    
    
public:
	//...
private:
	T* _a;
	size_t _size;
	size_t _capacity;
};

2. Instantiation of class templates

Class template instantiation is different from function template instantiation. Class template instantiation needs to be followed by the class template name <>, and then the instantiated type <>can be placed in it. The class template name is not the real class, but the instantiation result is the real class .

// Stack类名,Stack<int>是类型
Stack<int> s1;
Stack<double> s2

This is the end of this article, the code text is not easy, please support me a lot!

Guess you like

Origin blog.csdn.net/weixin_67401157/article/details/130748474