A little earlier, addressed the topic of function overloading in C++. You learned about the opportunity to write several functions with the same name, who perform the same tasks. The main difference between them – signature (parameter types and / or number of parameters). When the program starts, the compiler will choose, which of the overloaded functions apply(on the assumption that, that passed to the function)
The same templates allow functions to handle different data types, transmitted as parameters. But it is enough to write one common definition of a function. See how it looks.
By defining a function template we used C ++ reserved words: template and typename. template suggests that, that will now define the template. And in angle brackets aftertypenamegiven a conditional name of the data type. Here, instead of name T, you can assign any (very desirable correct) name.
Next is determined by the function itself. Specify the type of the return value T. Options: the number of type T, and the number of type int. This function finds the number and percentage of the value in the program returns. And the number, and the percentage passed as parameters. For example the first parameter we pass to an integer function (100). During start-up, the compiler will note that currently T this is int and replace the template functions, all these Ton int. Thus, the compiler function has the form:
We do not see clearly, but everything works great. Whatever the number, we have not passed to this function as the first parameter, the compiler will create an instance of a function template for any call. Here, the first parameter can be any type of data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream> using namespace std; template <typename T> T calcPercent(T number, int percent) { return number * percent / 100; } int main() { setlocale(LC_ALL, "rus"); cout << "20% от 200: " << calcPercent(200, 20) << endl; cout << "10% от 42.56: " << calcPercent(42.56, 10) << endl; return 0; } |
As a result, the screen will see the result of this calculation:
Speaking about the definition of a function template, i want to add, in angle brackets after the keyword template possible to record several conventional names for data types. Why you might need to do this? Consider this example:
It is necessary to write a function, which will take two numbers, determine the maximum of them and return it in the program. Will be given, that function, we can pass the number of different types. Possible and the case, one number is an integer, and the second – material. See what happens:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> using namespace std; template <typename T> T findMax(T firstNum, T secondNum) { if (firstNum > secondNum) return firstNum; else if (secondNum > firstNum) return secondNum; else return 0; } int main() { setlocale(LC_ALL, "rus"); cout << "Сравниваем 255 и 700! Большее = " << findMax(255, 700) << endl; cout << "Сравниваем 8.5 и 4.9! Большее = " << findMax(8.5, 4.9) << endl; // при передаче 2-х параметров с разными типами возникнет ошибка cout << "Сравниваем 100 и 5.1! Большее = " << findMax(100, 5.1) << endl; return 0; } |
The first and second parameters are defined function, as type parameters T. With function calls in strings 19-20 no problem, since the transfer parameters are of the same data type. Problems arise in the string 22 compile. And this is understandable. The compiler will get confused. He can not convert type int in double.
To work around this problem, it is necessary to write another template.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> using namespace std; template <typename T_1, typename T_2> T_2 findMax(T_1 firstNum, T_2 secondNum) { if (firstNum > secondNum) return firstNum; else if (secondNum > firstNum) return secondNum; else return 0; } int main() { setlocale(LC_ALL, "rus"); cout << "Сравниваем 255 и 700! Большее = " << findMax(255, 700) << endl; cout << "Сравниваем 8.5 и 4.9! Большее = " << findMax(8.5, 4.9) << endl; // ошибки не будет: cout << "Сравниваем 100 и 5.1! Большее = " << findMax(100, 5.1) << endl; return 0; } |
Heretypename T_1 indicates the type of parameter, that is passed in to the function first. typename T_2 respectively indicates the type of the second parameter. This version of the definition of the function template will alert errors, resulting in the transmission of different types of parameters.
It is important to remember,if you are in angle brackets give you a few names for conventional types of function parameters (as in our example), all these type names must be mentioned in the function signature. Otherwise avoid errors when compiling. For example is the definition of a template
It leads to the following errors:
The template we defined them conditional types T_1 and T_2, and the signature of the prescribed type onlyT_1 .
In practice, you can meet the definition of a function template in such a way, where instead of the keyword typename the use of the word class. For example:
it is equivalent to the definition of, which we considered
Previously, before the C ++ 98 standard, in templates always used the wordclass. Now better, when there was a keywordtypename , better to use it. Because it is more clearly says that, that the namesT_1 andT_2 They represent the type.
To summarize. The template function is designed to create a generalized description of the function. Such a function can take parameters of any type. The template allows the compiler to generate code for a specific function such as (or types) data, that was passed into it when you call.
Be sure to watch the video about templates:
strangely, I define a template, even if through T_1 program works correctly on =
A question, here's an example, where the function takes two arguments to the parameters T1 and T2, you have written, that the function will return the larger value of type T2, and if it would be a greater number of, which is a parameter T1 ? It is implicit to the T2 type with possible data loss ??
Yes, in the example shown, the return value of type T1, and if the second type T2 return, there will be an implicit conversion to T1.
What happens as a result – it is your responsibility to provide … for example, You can write an explicit conversion:
return static_cast( second );
why it can not be?
template
T_1 findMax(int a, double b)
{
if (a > b)
return a;
else if (b > a)
return b;
else
return 0;
}
template
T_1 findMax(int a, double b)
{
if (a > b)
return a;
else if (b > a)
return b;
else
return 0;
}
that is, so why can not?
template
T_1 findMax(int a, double b)
{
if (a > b)
return a;
else if (b > a)
return b;
else
return 0;
}
because, what is syntax rules, and it just will not work syntactical control.
A syntactic patterns rules say, that template types are written in angle brackets.
Website ate a piece of code, why it can not be?
#include
using namespace std;
template
T findMax(int a, double b)
{
if (a > b)
return a;
else if (b > a)
return b;
else
return 0;
}
int main()
{
cout << findMax(1, 5.42);
return 0;
}
where the template is still eaten site
taypneym T in angle brackets
So it is impossible for many reasons:
– mentioned generic type to be used in the function signature (this phrase is in the text)
– because the return (return) different types you are allowed only because, what is included permissible automatic conversion – it is a bad practice…
– better when returning to write explicit conversion:
return (T)b;
– and even better:
return static_cast( b);
P.S. Yes, forum engine (till?) He eats everything, in angle brackets … so I can not show you the correct static_cast… , Well, look in books.
Note (it is not accentuated in the text), what all, due to the template (function, classes) ** ** is processed by the preprocessor, means makroobrabotki text – before the beginning Best C ++ compile all the patterns revealed a code conversion.
Thank you