How much does a C + + template function know?

Source: Internet
Author: User

To tell a template function, let's take a look at an example, if the boss wants you to write a sort function, assuming that the first user's request might be an int. Then you've spent a lot of time writing a piece of code:

void sort (int* begin, int* end, BOOL (*CMP) (int, int))   ///The third parameter is a priority function, where I simply use the bubbling sort. If not sorted, do not delve into the sequencing implementation process. {int* I, *j;for (i = begin; I! = end; i++) {int* max = i;for (j = i + 1; J! = end, J + +) {if (CMP (*J, *max)) max = J;} int temp = *max;*max = *i;*i = temp;}} BOOL K (int a, int b) {return a > B;} int main () {int arr[6] = {1, 5, 3, 2, 6, 4}; Sort (arr, arr + 6, k); for (int i = 0; i < 6; i++) cout << arr[i] << ""; cout << Endl;return 0;}

OK, when you finish writing the code ready to credit to the boss, the boss said: The user asked again, asking not only to sort int can also be a double sort.

And then you're going to knock on your butt:

void Sort (double* begin, double* end, BOOL (*CMP) (double, double)) {double* I, *j;for (i = begin; I! = end; i++) {double* max = I;for (j = i + 1; J! = end; J + +) {if (CMP (*J, *max)) max = J;} Double temp = *max;*max = *i;*i = temp;}}


Well, you cleverly used the overloaded function to achieve this great demand (the amount, seemingly not great). When you are ready to credit, the boss said: "Ah sorry, the user has to ask again." He asked not only to sort to int,double also to be able to sort the C-style strings (char*), C + + style strings (string), custom structures. Oh yes, the user also wants to be a container or not necessarily an array sort.

You are dumbfounded: I am, how many overloads do you want to write this time? Well, let me tell you:

with Template!!!

After this example, we may not have any doubts about the necessity of the appearance of the grammatical sugar in the template. (Otherwise there are so many overloaded who will write Ah.) Trouble, but also prone to error).


I. Definition of template functions

So let's take a look at the following simple template example:

Template<typename t>void Say (T a) {cout << "this is;" << a << Endl;} int main () {Say (1); Say (2.3); Say (' a '); Say ("Love"); return 0;}

Here we define a template function, and we find that in the main function we can pass int, double, char, const char* and so on to this function. And can be passed in the parameters in the correct form of output.

Well, see here you see the benefits of template functions, then how do we use the template function?

For the example above: we just let this say only pass in int type, then the code is:

void Say (int a) {cout << "this is;" << a << Endl;}

This time we want to think of this say can be passed Double,char and so on the type of time to do? We think: Is it possible to use the type as a parameter? In this case, the type can be determined by the user?

The template appears to originate from this thought, and we see that before the function just add a word, template<typename t>.

The meaning of this sentence is:

1. The next function is a template function.

2. This function has a type parameter T.

So is it possible that the int of int A in the argument list of our function can be replaced by the type parameter of T?

Template<typename t>  //The typename here can be written as class, but try to use typenamevoid Say (T a) {cout << "this is;" << a < < Endl;}


In this case, you can use one more character to call this function Say (' C '). Then the template automatically translates this T into char. Then a function for char is generated.

Note: This function prototype is generated automatically by the compiler after encountering say (' a '). So the Say (' a ') call is actually the following function. void Say (char a) {cout << "this is;" << a << Endl;}

So the code contains the function template itself. bin does not generate a function definition, it is just a scenario for generating a function definition. When we call this function, the compiler will generate the corresponding function instance for the given parameter type.


From the above, we can see that we can call a template function without having to give the type argument as the argument. The compiler is automatically judged by the argument type.

A type parameter can be more than just one.

Template<typename t,typename f>void Func (T a,f b) {}

In addition to defining the type parameters in the template parameter list, you can also define normal parameters. However, if it is a normal parameter then the variable in the function is constant, and the function must be explicitly given the type when it is called:

Template<typename t,int num>void Func (T arr) {for (int i = 0; i < num; i++) cout << arr[i] << ""; cout << Endl;} int main () {int arr[5] = {1, 2, 3, 4, 5}; func<int*, 3> (arr);  The type return 0 must be explicitly given in <>.}

Basically the simple definition of a template function is so, let's look at some of the things we need to be aware of using template functions:


1. The template parameter cannot be empty. Once you declare a template function, you can use the formal parameters of the template function to name the member variables and member functions in the class, that is, the template parameter names can be used wherever the built-in type is used in the function.

2. If you define a normal parameter in the template parameter list, you can only give the constant expression when the argument is passed in. and the parameter exists as a constant in the function.

3. variable coverage issues: variables for global variables < template argument Lists < variables for function argument lists (local variables inside functions). The left-hand variable can be overridden by the variable with the same name on the right.

4. the template parameter name can only be used once in the same template parameter table, but the template argument name may be reused between multiple function template declarations or definitions.

5. As with non-template functions, a function template can also be declared inline or extern should put the indicator behind the template parameter table instead of the keyword template.


Well here you must have been able to solve the problem that the boss left to you very well. Here's the code:

Template<typename t>void Sort (t begin, T end, BOOL (*CMP) (T, T)) {T I, j;for (i = begin; I! = end; i++) {T max = I;for (j = i + 1; J! = end; J + +) {if (CMP (J, max)) max = J;} Auto temp = *max;*max = *i;*i = temp;}} BOOL Cmp1 (double* A, double* b) {return *a > *b;} BOOL Cmp2 (Vector<int>::iterator A, Vector<int>::iterator b) {return *a > *b;} int main () {double Arr[6] = {1, 5, 3, 2, 6, 4}; Sort (arr, arr + 6, CMP1);                   You can sort the array vector<int> Varr = {1, 5, 3, 2, 6, 4}; Sort (Varr.begin (), Varr.end (), CMP2);      The container can also be sorted for (int i = 0; i < 6; i++) cout << arr[i] << ""; cout << endl;for (int i = 0; I < 6; i++) cout << varr[i] << ""; cout << Endl;return 0;}

After reading the code, you will find that the third parameter (priority function) of our sort function is not enough to be reused, so C + + introduces the concept of an imitation function (function object). For more information, see the ——— profiling function


Two. Specialization of template functions (explicit materialization) and explicit instantiation


The last time you skillfully use the characteristics of the template to quickly solve the user's needs, the boss of this greatly praised you.

This time, the boss found you again, said a user wants you to help them write an addition function (if the string should be used as a connection function). For the two parameters passed in, the return value can be sent out after the addition.

It's not easy for you to think about it. Template functions have been learned, such a requirement is simply a small case. So soon you're ready to write the code:

Template<typename t>t void Add (t A, T B) {return a + B;}

When you're ready to give it to the boss, you think, no, what if the char* (C-style string) is passed in? Can't add two char*!

So here you need to char* this special type to deal with it alone! To solve this problem, the template function gives a solution to the problem ———— explicit materialization

The syntax for displaying materialization is this:

Note that the function template explicitly does not exist in the type parameter template<>    ///Here the template followed by <> indicates that this is an instantiation of the ADD function template char* add<char*> (char* A, char* b)    //The function name here is followed by a <> filled with the specified type of specificity.  {char* newstr = new Char[strlen (a) + strlen (b) + 1];for (int i = 0; i < strlen (a); i++) Newstr[i] = a[i];for (int i = 0; I < strlen (b); i++) Newstr[i + strlen (a)] = B[i];newstr[strlen (a) + strlen (b)] = ' + '; return newstr;}

In that case, the code you give to the boss is the integration of templates and explicit materialization:

C++test.cpp: Defines the entry point of the console application. #include "stdafx.h" #include <typeinfo> #include <string.h> #include <vector>using namespace std; Template<typename t>t Add (t A, T B) {return a + B;} Note that the function template explicitly does not exist in the type parameter template<>    ///Here the template followed by <> indicates that this is an instantiation of the ADD function template char* add<char*> (char* A, char* b)    //The function name here is followed by a <> filled with the specified type of specificity.  {char* newstr = new Char[strlen (a) + strlen (b) + 1];for (int i = 0; i < strlen (a); i++) Newstr[i] = a[i];for (int i = 0; I < strlen (b); i++) Newstr[i + strlen (a)] = B[i];newstr[strlen (a) + strlen (b)] = ' + '; return newstr;} int main () {ADD (1, 3); ADD ("123", "123"); return 0;}

Let's take a look at what an explicit instantiation is:

Let's take a look at the addition of the above function template:

Template<typename t>t void Add (t A, T B) {return a + B;}

If we call this in the source file: Add (2,2.3). What's going to happen?

Oh, some people may think this: the type of int can be implicitly converted to double so actually call is add<double> (2,2.3);

In fact, this is not the case, in the function template of the argument and parameter matching is the use of real argument deduction. That means. When you call ADD (2,2.3), the compiler will go to the non-template function and find the template Add (int,double) that can be instantiated as a function when it is not found. Found, and then error!!

Is there no way out? Actually, there is. We can explicitly specify the template type parameter!!

Add<double> (2,2.3). In this case, the compiler does not make an argument deduction, directly from the double generated by the previous double to generate the add template. The arguments are then passed in. The int can then be converted implicitly.

Template<typename t>t Add (t A, T B) {return a + B;} int main () {add<double> (1, 2.3);    This is called an explicit instantiation. return 0;}

Then the question comes again. We know that string and char are additive (overloaded with the + operator in the string library) and that the addition result is of type string.

For the following addition template we can call add (' a ', string (' BC ')) or add (String ("AB"), ' C ').

<pre name= "code" class= "CPP" >template<typename t,typename f>___ Add (T A, F b) {return a + B;}

You can see the above template, I have empty the return value. Why is it? Because the return value is not T or F. Instead of the value that should be obtained after T + F.

For example: When I call this, add (' A ', string (' BC ')) corresponds to Char, and f is string. The return value type is f (string). Instead, if I call Add this way (string ("AB"), ' C '). The return value type is T.

So we prefer that our templates intelligently recognize the types that should be returned: so we have the syntax for the post return type

Template<typename t,typename F>auto Add (T A, F b), Decltype (a+b) {return a + B;}


Generic function templates are placed in the header file declaration, and if there is a special type that requires special action by the function, it can be explicitly materialized in the source file. If this function is called, the compiler will first go to the display materialized to find the matching function.


So how does the compiler know where to look for a definition or, when there are multiple definitions to use, which one is preferred?

For details, see ———————— overload resolution

How much does a C + + template function know?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.