[C++ Basic Knowledge] Generic Programming--Template

Generic programming

First think about a question: how to implement a universal exchange function?

Many people here may think of function overloading. Yes, function overloading can realize the exchange of different types of data, but it also has big flaws:

  1. Overloaded functions are only different in types, and the code reuse rate is relatively low. As long as new types appear, the corresponding functions need to be added
  2. The maintainability of the code is relatively low, and an error may cause all overloads to go wrong

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

The concept of
generic programming will be printed here. Generic programming: Writing generic code that has nothing to do with types is a means of code reuse. Templates are the foundation of generic programming.

Function template

concept:

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

Function template format

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

template<typename T>
void Swap( T& left, T& right) {
    
    
 T temp = left;
 left = right;
 right = temp; }
//注意:typename是用来定义模板参数的关键字
//也可以使用class(切记:不能使用struct)

In the compilation stage of the compiler, for the use of template functions, the compiler needs to deduce and generate the corresponding type of function for calling based on the type of the actual parameter passed in.
For example, when using a function template with the double type, the compiler determines T as the double type by deducing the type of the actual parameter, and then generates a code that deals with the double type, and the same is true for the character type.

Instantiation of function templates

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

If the types do not match, the compiler will try to perform implicit type conversion. If the conversion fails, the compiler will report an error.

Parameter matching principle of function template

  1. A non-template function can exist at the same time as a function template with the same name, and the function template can also be instantiated as this non-template function
  2. 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. If the template can produce a function with a better match, then the template will be selected
  3. Template functions do not allow automatic type conversion, but ordinary functions can perform automatic type conversion

Class template

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>
Vector<T>::~Vector()
{
    
    
 if(_pData)
 delete[] _pData;
 _size = _capacity = 0; }

Instantiation of class template

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

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

Guess you like

Origin blog.csdn.net/weixin_43962381/article/details/114990116