Article Directory
Foreword:
In this chapter, we will learn templates and formally contact generic programming.
C++
Compared withC
languages, there are so many rich interfaces and types, all of which originate from generic programming.STL
The 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:
- 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
- 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:
typename
The following content does not have to beT
, it can be freely specified;typename
It is used to define template parameter keywords , and can also be usedclass
(remember: cannot be usedstruct
insteadclass
)
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).
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 doubl
by 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.T
double
double
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;
}
(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:
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
a
will 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.T
int
d
T
double
T
T
int
double
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;
}
② 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;
}
Notice:
- In the following case, the function called twice
swap
is 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:
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;//使用模板
}
③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!