C++ Getting Started Guide: 10 minutes to help you quickly understand what templates are (recommended to collect!!)


Insert image description here


1. Generic programming (template introduction)

How to implement a general exchange function?

void Swap(int& left, int& right)
{
    
    
	int temp = left;
	left = right;
	right = temp;
}
void Swap(double& left, double& right)
{
    
    
	double temp = left;
	left = right;
	right = temp;
}
void Swap(char& left, char& right)
{
    
    
	char temp = left;
	left = right;
	right = temp;
}

Although it can be achieved using function overloading, it has several disadvantages:

  1. Overloaded functions only have 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, and one error may cause errors in all overloads.

To this end, C++ introduces generic programming, allowing the compiler to use this model to generate code according to different types! !
Generic programming: Writing universal code that is independent of type is a means of code reuse. Templates are the basis of generic programming.

Insert image description here


2. Function template

Insert image description here

2.1 Function template concept

A function template represents a family of functions that are type-independent and are parameterized when used to produce a type-specific version of the function based on the actual parameter types.

2.2 Function template format

template<typename T1, typename T2,…,typename Tn>
Return value type function name (parameter list)
{ }

Note:typename is used to define template parameter keywords, and class can also be used (remember: struct cannot be used instead of class)

Exchange function template example:

//template<class T>
template<typename T>
void Swap(T& a, T& b)
{
    
    
	T temp = a;
	a = b;
	b = temp;
}

2.3 Principles of function templates

The function template is a blueprint. It itself is notnot a function, but is generated by the compiler using usage Mold for a function of a specific concrete type.
In the compiler compilation stage , for the use of template functions, the compiler It is necessary to deduce and generate a function of the corresponding type based on the type of the actual parameters passed in for calling.
[Illustration]:
Insert image description here
When using the function template with double type, the compiler determines T as double type through deduction of the actual parameter type, and then generates A code that specifically handles double types. The same applies to others.

2.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.

2.4.1 Implicit instantiation

implicit instantiation: lets the compiler deduce the actual type of the template parameter 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.0, d2 = 20.0;
	 Add(a1, a2);
	 Add(d1, d2);
 
 /*
  Add(a1, d1);
 该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型
 通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,
 编译器无法确定此处到底该将T确定为int 或者 double类型而报错
 注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅
 */
 
	 // 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
	 Add(a, (int)d);
	 return 0;
}

2.4.2 Display instantiation

== Explicit instantiation==:Specify the actual type of the template parameter in the <> after the function name.

int main(void)
{
    
    
	 int a = 10;
	 double b = 20.0;
 
	 // 显式实例化
	 Add<int>(a, b);
	 return 0;
}

2.5 Matching principles 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
// 专门处理int的加法函数
int Add(int left, int right)
{
    
    
	 return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
    
    
	 return left + right;
}
void Test()
{
    
    
	 Add(1, 2); // 与非模板函数匹配,编译器不需要特化
	 Add<int>(1, 2); // 调用编译器特化的Add版本
}
  1. For non-template functions and function templates with the same name, if other conditions are the same, the non-template function will be called first when calling and an instance will not be generated from the template. The template will be chosen if it can produce a function with a better match.
// 专门处理int的加法函数
int Add(int left, int right)
{
    
    
	 return left + right;
}
// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
    
    
 	return left + right;
}
void Test()
{
    
    
 Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
 Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}

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


3. Class template

Class templates are not checked, similar to macro replacement! !
Insert image description here

3.1 Definition format of class template

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

[Example]:

// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>
class Vector
{
    
     
public :
	 Vector(size_t capacity = 10)
 		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
 {
    
    }
 
 // 使用析构函数演示:在类中声明,在类外定义。
 ~Vector();
 
 void PushBack(const T& data)void PopBack()// ...
 
 size_t Size() {
    
    return _size;}
 
 T& operator[](size_t pos)
 {
    
    
	 assert(pos < _size);
	 return _pData[pos];
 }
 
private:
T* _pData;
size_t _size;
size_t _capacity;
};

// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
//不同类的类名即类型,但类模板不同:类型(类名 + <T>)
Vector<T>::~Vector()
{
    
    
 if(_pData)
 delete[] _pData;
 _size = _capacity = 0;
}

3.2 Instantiation of class templates

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

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

Guess you like

Origin blog.csdn.net/Zhenyu_Coder/article/details/133975955