[C ++ in-depth analysis] 42, function template and its essential analysis

For functions with the same function body, only functions with different parameter types can be solved using function templates. This is a generic programming in C ++.

1 Function template

Function template is a special function that can be called with different types,
Insert picture description here

1.1 Syntax rules for function templates

  • The template keyword is used to declare the start of generic programming
  • The typename keyword is used to declare generic programming

Insert picture description here

1.2 Use of function templates

  • Automatic type inference call
  • Specific type display call

The usage is as follows:
Insert picture description here

Programming experiment: a preliminary exploration of template functions

// 42-1.cpp
#include<iostream>
#include<string>
using namespace std;
template<typename T>
void Swap(T& a, T& b)
{
    T c = a;
    a = b;
    b = c;
}
template<typename T>
void Sort(T a[], int len)
{
    for (int i = 0; i < len; i++)
    {
        for (int j = i; j < len; j++)
        {
            if (a[i] > a[j])
            {
                Swap(a[i], a[j]);
            }
        }
    }
}
template<typename T>
void print(T a[], int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << a[i] << ", ";
    }
    cout << endl;
}
int main()
{
    int a[5] = {4, 5, 1, 3, 2};
    Sort(a, 5);
    print(a, 5);
    string s[5] = {"Java", "C++", "Go", "Python", "C"};
    Sort(s, 5);
    print(s, 5);
    return 0;
}
$ g++ 42-1.cpp -o 42-1
$ ./42-1
1, 2, 3, 4, 5, 
C, C++, Go, Java, Python, 

2 The essence of function templates

The compiler compiles the function template twice

  • Compile the template itself
  • Compile the code after parameter replacement

Note: The function template itself does not allow implicit type conversion

  • When deriving types automatically, they must be strictly matched
  • When the display type is specified, implicit type conversion can be performed

Programming experiment: the essence of function templates

// 42-2.cpp
#include<iostream>
using namespace std;
class Test
{
    Test(const Test&);
public:
    Test()
    {
    }
};
template<typename T>
void Swap(T& a, T& b)
{
    T c = a;
    a = b;
    b = c;
}
// 使用typedef定义函数类型
typedef void(FuncI)(int&, int&);
typedef void(FuncD)(double&, double&);
typedef void(FuncT)(Test&, Test&);
int main()
{
    FuncI* pi = Swap;
    FuncD* pd = Swap;
    //FuncT* pt = Swap;
    cout << "pi = " << reinterpret_cast<void*>(pi) << endl;
    cout << "pd = " << reinterpret_cast<void*>(pd) << endl;
    //cout << "pt = " << reinterpret_cast<void*>(pt) << endl;
    return 0;
}
  • Use typedef to define three function types. The function template compiler needs to compile once, and the code after parameter replacement must also be compiled once. On lines 25 and 26, the two pointers point to two specific functions.
  • The copy constructor in class Test is defined as private, but when generating specific code, the private constructor cannot complete the assignment and will compile errors. It is verified again that the compiler must compile the template itself, and also compile the replaced code.

Compile and run

$ g++ 42-2.cpp -o 42-2
$ ./42-2
pi = 0x55daa8490a01
pd = 0x55daa8490a2e

You can see that the address of the function pointer is different.

3 Multi-parameter function template

  • Function templates can define any number of different types of parameters

Insert picture description here
For multi-parameter function templates

  • The return value type cannot be derived automatically
  • Type parameters can be specified from left to right

Insert picture description here
The return value parameter as the first type parameter in the project

Programming experiment: multi-parameter function template

// 42-3.cpp
#include<iostream>
using namespace std;
template<typename T1, typename T2, typename T3>
T1 add(T2 a, T3 b)
{
    return static_cast<T1>(a + b);
}
int main()
{
    int r1 = add<int>(0.5, 0.8);
    double r2 = add<double, float>(0.5, 0.8);
    float r3 = add<float, float, float>(0.5, 0.8);
    cout << "r1 = " << r1 << endl;
    cout << "r2 = " << r2 << endl;
    cout << "r3 = " << r3 << endl;
    return 0;
}
  • Use the first parameter to specify the return value type. When solving r1, T1 is int, T2 is double, and T3 is double
  • When solving r2, T1 is double, T2 is float, and T3 is double
  • When solving r2, T1 is float, T2 is float, and T3 is float
$ g++ 42-3.cpp -o 42-3
$ ./42-3
r1 = 1
r2 = 1.3
r3 = 1.3

4 Function templates meet function overloading

Function templates can be overloaded like ordinary functions

  • Prioritize ordinary functions
  • If the function template can produce a better match , select the template
  • You can restrict the compiler to match only the template with an empty template argument list

Insert picture description here

// 42-3.cpp
#include<iostream>
using namespace std;
template<typename T>
T MAX(T a, T b)
{
    cout << "T MAX(T a, T b)" << endl;
    return a > b ? a : b;
}
int MAX(int a, int b)
{
    cout << "int MAX(int a, int b)" << endl;
    return a > b ? a : b;
}
template<typename T>
T MAX(T a, T b, T c)
{
    cout << "T MAX(T a, T b, T c)" << endl;
    return MAX(MAX(a, b), c);
}
int main()
{
    int a = 1;
    int b = 2;
    cout << MAX(a, b) << endl << endl;			// 普通函数 MAX(int, int)
    cout << MAX<>(a, b) << endl << endl;		// 函数模板 MAX<int>(int, int)
    cout << MAX(3.0, 4.0) << endl << endl;		// 函数模板 MAX<double>(double, double)
    cout << MAX(5.0, 6.0, 7.0) << endl << endl;	// 函数模板 MAX<double>(double, double, double)
    cout << MAX('a', 70) << endl << endl;		//  普通函数 MAX(int, int)
    return 0;
}

Priority is given to ordinary functions; if the function template has a better match, the template is selected; you can also use the empty template argument list to match only the template

Compile and run

$ g++ 42-4.cpp -o 42-4
$ ./42-4
int MAX(int a, int b)
2

T MAX(T a, T b)
2

T MAX(T a, T b)
4

T MAX(T a, T b, T c)
T MAX(T a, T b)
T MAX(T a, T b)
7

int MAX(int a, int b)
97

5 Summary

1. The function template can deduce the parameter type according to the actual parameters.
2. It can automatically deduce and call the type. It can also display the specified parameter type.
3. The function template generates different functions according to the specific type.
4. The cold template can define multiple different type parameters
5. Function templates can be overloaded

Published 298 original articles · praised 181 · 100,000+ views

Guess you like

Origin blog.csdn.net/happyjacob/article/details/104505401