C ++: Introduction and demonstration of function templates


Generic programming

How to implement a universal 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 function overloading can be achieved, there are a few disadvantages:

  1. Overloaded functions are only different types, the code reuse rate is relatively low, as long as there are new types, you need to add corresponding functions

  2. The maintainability of the code is relatively low, one error may cause all overloads to go wrong

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

In fact, in C ++, there is such a mold , by filling the mold with different types , to generate different specific types of code .

Generic programming: writing generic code independent of type is a means of code reuse. Templates are the foundation of generic programming.

Insert picture description here

Function template

Function template concept

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 actual parameter type.

Function template format

Code example:

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

 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 , you can also use class (remember: you can not use struct instead of class)

Principles of function templates

A template is a blueprint. It is not a function in itself. It is a mold that the compiler uses to generate a specific type of function. So in fact, the template is to hand over the repetitive things that we should do to the compiler.
Insert picture description here
At the compiler compilation stage , for the use of template functions, the compiler needs to derive the corresponding type of function for the call based on the incoming argument type . For example, when using a function template with a double type, the compiler determines T as a double type by deducing the actual parameter type , and then generates a code that specifically handles the double type , as does the character type.

Function template instantiation

When a function template is used with different types of parameters , 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 infer the actual type of template parameters 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);

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

Template parameter matching principle

  1. 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
 // 专门处理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 the non-template function and the function template with the same name, if the other conditions are the same, the non-template function will be called preferentially during the transfer without generating an instance 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函数
}
  1. There is no implicit type conversion in the function template in the process of passing parameters, but ordinary functions can perform implicit type conversion
template <typename T>
void test_fuc(T& t1, T& t2)
{
    cout << "template...\n";
}

void test_fuc(int a, char b)
{
    cout << "ordinary fuction...\n";
}

int main()
{
    int a = 1;
    char b = 0;
    
    test_fuc(b, a);	//访问普通函数,因为模板函数不能有隐式转化,必须严格匹配,普通函数则不同。
    
    return 0;
}

If you have different opinions, please leave a message to discuss!

Published 152 original articles · praised 45 · 10,000+ views

Guess you like

Origin blog.csdn.net/AngelDg/article/details/104913654