A first look at C++ templates-generic programming, function templates and class templates


Insert picture description here

One, generic programming

1.1 Why use generic programming?

For writing a general exchange function, we can use function overloading. The specific details of function overloading can be found in the following blog:
C++ Elementary-Namespace, default parameters and function overloading

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;
}

The use of function overloading can achieve general exchange functions, but there are two problems

  • Function overloading is only the type is different , the code reuse rate is low, when a new type appears, the corresponding function must be added ;
  • Code maintainability is low, and one error causes all overloads to go wrong.
    Therefore, people think of a way to tell the compiler a model, let the compiler use the model to generate code according to different types , which leads to generic programming .

2.2 What is 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 .

Insert picture description here

Two, function template

2.1 What is a function template?

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 .

2.2 How to use function template?

<1> Function template format

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}
Here is a chestnut:

//2.2 
template<typename T>
void Swap(T& left, T& right)
{
    
    
	T temp = left;
	left = right;
	right = temp;
}

note

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

2.3 Principle of Function Template

Function template is a blueprint, which itself is not a function , a compiler of the mold to produce a particular use of particular types of functions . So in fact, the template is to hand over the repetitive things that we should have done to the compiler.
Insert picture description here
During the compilation phase of the compiler, for the use of template functions, the compiler needs to deduce and generate the corresponding type of function for calling according to 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.

<1> Function template instantiation

When a function template is used with different types of parameters , it is called the 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
    Insert picture description here
  2. Explicit instantiation: Specify the actual type of the template parameter with the <> after the function name.
    Insert picture description here
    If the type does not match, the compiler will try to perform an implicit type conversion. If the conversion fails, the compiler will report an error.

<2> The matching principle of template parameters

  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 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版本
}

int main()
{
    
    
	Test();
	return 0;
}

Insert picture description here
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 during the transfer 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 .

// 专门处理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函数
}

Insert picture description here
3. Template functions do not allow automatic type conversion, but ordinary functions can perform automatic type conversion

Three, class template

3.1 Definition format of class template

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

The use of class templates is to solve the problem of storing different types of data in the class , for example:

// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>
class Vector
{
    
    
public:
	Vector(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{
    
    }
	// 析构函数
	~Vector()
	{
    
    
		if(_pData)
			delete[] _pData;
		_size = _capacity = 0;
	}
	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;
};

It should be noted here that if we declare the function in the class to be defined outside the class, then we need to add the template parameter list, such as the destructor
Insert picture description here

3.2 Instantiation of a class template

How to use the above class template?

Class template instantiation is different from function template instantiation. Class template instantiation needs to be inClass template name followed by <>,thenPut the instantiated type in <>That is, the class template name is not the real class, but the result of instantiation is the real class.

int main()
{
    
    
	Vector<int> s1;
	Vector<double> s2;
	Vector<char> s3;
	return 0;
}

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_40076022/article/details/114852730