C + + function template

1. What is a template? What does the template do?
Templates are divided into function templates and class templates. Function template is a description of the function framework. The specific function is determined by the actual parameters passed.
With a function template, the compiler will automatically generate multiple functions with the same function name and different parameter lists according to the template, which does not need to be written manually;
Example: find a rectangular area
When the length and width of the input are positive integers, we need to write the function as follows:

void Rectangle(int a,int b)
{
   int s;
   s=a*b;
   cout<<"s="<<s<<endl;
}

However, if the length and width of the input are decimal, we need to write this:

void Rectangle(double a,double b)
{
   double s;
   s=a*b;
   cout<<"s="<<s<<endl;
}

It can be found that such realism is cumbersome, the form is the same, and it needs to be written on both sides. In order to solve this problem, there is a function template.
2. How should function templates be used?
The function template is written as follows:

template<typename Type parameter 1, typename Type parameter 2>
Return value type template name(Formal parameter name)
{
   Function body;
}

For the above program, we can define such a function template:

template<typename T>
void Rectangle(T&x,T&y)
{
  T s;
  s=x*y
  cout<<"s"<<s<<endl;
}
T Is a type parameter that represents the type of the incoming parameter. When a function is generated from a template, it will automatically replace the type parameters in the template according to the type of the arguments.

3. What is the difference between a function template and a template function?
The specific function to which a template is instantiated is called a template function (instantiation: the process in which the compiler automatically replaces the template to generate a specific function is called instantiation);
The function template will generate corresponding functions according to usage during compilation
The template is not compiled;
However, the function instructions generated by the template will be compiled;
Syntax errors in the template will be compiled when generating corresponding instructions;
Function templates have the ability of type self pushing. You can use function templates without passing template type parameters;
For the above procedure:

template<typename T>
void Rectangle(T&x,T&y)
{
  T s;
  s=x*y
  cout<<"s"<<s<<endl;
}

This is the function template

void Rectangle(int a,int b)
{
   int s;
   s=a*b;
   cout<<"s="<<s<<endl;
}
void Rectangle(double a,double b)
{
   double s;
   s=a*b;
   cout<<"s="<<s<<endl;
}

This is a template function

Let's take a look at a small code:

template<typename T>
bool compare(T a, T b)
{
	cout << "template<typename T> bool compare(T a, T b)" << endl;
	cout << typeid(T).name() << endl;
	return a > b;
}
int main()
{
	compare(10, 20);
	compare(10.2, 20.3);
	//compare<int>(10, 20);
	//compare<double>(10.2, 20.3);
}

When the compiler instantiates the template, the type parameters of the template can not only be judged by passing in the arguments, but also directly indicate the type of the type parameter to be instantiated. (the part shielded by the above program).
The template functions instantiated here are:

bool Compare(double a,double b);

It should also be noted that when specifying types, you can specify multiple types, such as:

compare<doubleļ¼Œfloat>(10.2, 20)

Even if it is not specified, the compiler will replace it with the corresponding type, that is:

compare<double>(10.2, 20)//The type of 20 is int

Similarly, if it is not specified or identified according to the arguments, different types will be identified, that is:

  compare(10.2, 20);//10.2 is double and 20 is int

Example: write a bubble sort template

template<typename T>
void swap1(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}
template<typename T>
void sort(T* arr, int len)
{
	cout << "void sort(T *arr,int len)" << endl;
	cout << typeid(T).name() << endl;
	if (NULL == arr)
	{
		return;
	}
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (!(arr[j] > arr[j + 1]))
			{
				swap1(arr[j], arr[j + 1]);
			}
		}
	}
}

int main()
{
	int arr[] = { 23,45,34,11,67,89,4,3,90,21 };
	double arr[] = { 23,45,34,11,67,89,4,3,90,21 };
	int len = sizeof(arr) / sizeof(arr[0]);
	sort(arr, len);
	return 0;
}

The bubble sort function template will automatically generate the following two functions during compilation:

void sort(int *arr,int len);
void sort(double *arr,int len);

4. Specialization of function templates
Question: what is specialization and why?
A: as the name suggests, specialization is a special instantiation of a function template. It is used to complete special tasks that half of the template functions cannot complete. Example:
Or the code just now:

template<typename T>
bool compare(T a, T b)
{
	cout << "template<typename T> bool compare(T a, T b)" << endl;
	cout << typeid(T).name() << endl;
	return a > b;
}
int main()
{
	if (compare("aaa", "sss"))//The address will be directly compared, and the comparison result is not trusted
	{
		cout << "aaa > sss" << endl;
	}
	else
	{
		cout << "sss > aaa" << endl;
	}
	For general numerical comparison, the template function above is OK, but if both arguments are strings, their argument types are in place`const char*`Type.
	As we all know, when comparing strings, we compare the characters one by one, so that the result is credible. However, if we still call the template function above to compare, it is not the compared string, it compares the address of the whole string. The result is that the left is always larger than the right
}

The above code can be seen at a glance that sss is large. The correct answer should be sss > AAA. The print results are as follows:

We found that this result is obviously incorrect.

By observing the address, it can be found that the address of aaa is larger than that of sss, which shows that for special arguments such as strings, we can't compare them with ordinary template functions. We must write a special case of another template function to solve these problems, that is:

template<>
bool compare(const char* a, const char* b)
{
	cout << "bool compare(const char* a, const char* b)" << endl;
	return strcmp(a, b) > 0;
}

The results are as follows:

We found the result correct.

Explanation: specialization does not overload the function template. On the contrary, it is only a special template function instantiated by the function template. When writing this kind of specialization template function, you need to write the parameter type directly in the formal parameter parameter list, and you can no longer use the type parameter.
Special cases can be divided into partial special cases and full special cases. All special cases are the above, in which both parameters are written in the parameter type. Partial special cases are only some parameters written in the parameter type, such as:

template<T>
bool compare(T a,int b);

5. Class template
Let's clarify a definition first. The instantiation of a class template is a template class.
Class template is actually to create a general class. The return value types and parameter types of internal data members and member functions are not specified, but are represented by type parameters. When using class template to define objects, the system will replace the type parameters in the template according to the type of arguments, so as to instantiate a template class to realize specific functions.
The format is as follows:

template<typename Type parameter>
class Class name
{
   Class member description
};

When you need to implement specific functions, you need to establish a specific class template, such as calculating the rectangular area

template<typename T>
class Rectangle
{ 
public: 
    Rectangle(T a,T b)
    { 
        x=a;
        y=b;
    }
    T Area()
    {
        return a*b;
    }
private:
    int x,y;
}
int main()
{
	Rectangle<int>a(10, 20);
}

Note: class template
Class templates are not compiled
The corresponding class code will be generated according to the usage mode during compilation
Member methods not used in the class template will not generate corresponding instructions in the compiler
Template type parameters must be added when using class templates. Class templates cannot derive type parameters themselves
Why can't member methods of class templates be implemented in other cpp files?
Class templates need to generate corresponding instructions for the member methods to be used during compilation
The compiler is a pointer to a single file
If the member method of the class template is implemented in other files, and the file using the method during compilation is not visible, the corresponding instruction cannot be generated -- unresolved external symbols will be reported

Look at another code:

template <typename T>
class Arr
{
public:
	Arr(T x,T y)
	{
	    a=x;
	    b=y;
		cout << "Arr()" << endl;
	}
	T Area();
private:
    T a,b;
};

//Implementation of member methods outside class of class template
template<typename T>
void Arr<T>::Area()
{
     return x*y;
	cout << "void Arr<T>::Area()" << endl;
}

int main()
{
    Arr<int>A(1,2);
    Arr<float>B(2,3);
    Arr<double>C(3,4);
    return 0;
}

In the above code, after the class template is instantiated, three template classes are generated, and three objects A, B and C are generated.
Note: when the member function of a class is implemented outside the class, it is necessary to declare the template before the function definition, and write "class name::" before the member function name;

Tags: C++

Posted on Sun, 28 Nov 2021 17:22:26 -0500 by sone_br