Hello everybody
Till now, we have been seeing the powerful of templates but, like I showed,
sometimes we can get some unexpected results so I like to check out this topic, argument deduction
There are so many times that C++ compiler must conclude that T must
be int or any type, what becomes this?
An example we unexpected:
Example:
std::cout << mySpace::max(15,21.1) << std::endl;
This call returns 21 (with warning), the comparison works perfectly but at the moment to return value, it's needed an int, so have to truncate the double. In fact, it's not as simple as truncate and the code instance a local variable (temporaly), making that our return definacion as constant is not exaclty correct, so makes a warning.
Therefore, it may sense to define a returning type, a new template, example:
In this way, we can control types and how RT can't be deduced we have to list explitly each template type..
Another approach is to specify only the return type, in general we must specify all the argument types up to the last argument that cannot be determined by deduction progress.
Thus, if we change the order of the templates we could only specify RT, let's see:
Till now, we have been seeing the powerful of templates but, like I showed,
sometimes we can get some unexpected results so I like to check out this topic, argument deduction
There are so many times that C++ compiler must conclude that T must
be int or any type, what becomes this?
An example we unexpected:
#include <iostream> #include <complex> namespace mySpace{ // getting sure that this is the class we call becouse std::max is implemented template < class T > // for any class/typename T inline const T& max (const T& a, const T& b){ // return a>b?a:b; // where the operator '>' is implemented } } int main(){ std::cout << mySpace::max(10,20) << std::endl;// works perfectly as we saw //std::cout << mySpace::max(15,21.1) << std::endl;// error: no matching function for call to ‘max(int, double)’ //std::cout << mySpace::max('a',21) << std::endl;// error: no matching function for call to ‘max(char, int)’ //some ways to fix it: // static_cast is a powerful tool, and I'm going to explain it while course std::cout << mySpace::max(static_cast<double>(15),21.1) << std::endl; // double(x) call the costructor of double, so 15 is an double std::cout << mySpace::max(double(15),21.1) << std::endl; // this is a bad practice, this cast is highlighting to the compiler that is a double //in this case works, but take care it std::cout << mySpace::max((double)15,21.1) << std::endl; //and the first solucion where we really use templates //we are forcing that max's call have to be doouble std::cout << mySpace::max<double>(15,21.1) << std::endl; //this examples also works but returning types is unexpected //we unlike 97's answer, we wanted a, as char //but our template function is unable to do it std::cout << mySpace::max<int> ('a',21) << std::endl; //This works too but don't make much sense std::cout << mySpace::max(int('a'),21) << std::endl; return 0; }This may appear to be a good method to enable passing two call parameters. Thus, we'll have two templates types as arguments.
Example:
#include <iostream> #include <complex> namespace mySpace{ // getting sure that this is the class we call becouse std::max is implemented template < class T1 , class T2 > // for any class/typename T inline const T1& max (const T1& a, const T2& b){ // return a>b?a:b; // where the operator '>' is implemented } } int main(){ std::cout << mySpace::max(10,20) << std::endl;//no problems //Now, the errors we had, have been fixed but isn't enough std::cout << mySpace::max(15,21.1) << std::endl; std::cout << mySpace::max('a',21) << std::endl; //both of us calls makes this warning //main.cpp:14:37: instantiated from here //main.cpp:6:22: warning: returning reference to temporary return 0; }This template method have some issues, for example, we're defining the return type with the first argument, then:
std::cout << mySpace::max(15,21.1) << std::endl;
This call returns 21 (with warning), the comparison works perfectly but at the moment to return value, it's needed an int, so have to truncate the double. In fact, it's not as simple as truncate and the code instance a local variable (temporaly), making that our return definacion as constant is not exaclty correct, so makes a warning.
Therefore, it may sense to define a returning type, a new template, example:
#include <iostream> #include <complex> namespace mySpace{ // getting sure that this is the class we call becouse std::max is implemented template < class T1, class T2, class RT > // for any class/typename T inline RT max (const T1& a, const T2& b){ //Note that return type isn't constant return a>b?a:b; // where the operator '>' is implemented } } int main(){ //correct but tedious std::cout << mySpace::max<int,double,double>(15,21.1) << std::endl; std::cout << mySpace::max<char,int,char>('a',100) << std::endl; return 0; }
In this way, we can control types and how RT can't be deduced we have to list explitly each template type..
Another approach is to specify only the return type, in general we must specify all the argument types up to the last argument that cannot be determined by deduction progress.
Thus, if we change the order of the templates we could only specify RT, let's see:
#include <iostream> #include <complex> namespace mySpace{ // getting sure that this is the class we call becouse std::max is implemented template < class RT, class T1, class T2 > // for any class/typename T inline RT max (const T1& a, const T2& b){ //Note that return type isn't constant return a>b?a:b; // where the operator '>' is implemented } } int main(){ std::cout << mySpace::max<double>(15,21.1) << std::endl; std::cout << mySpace::max<char>('a',100) << std::endl; std::cout << mySpace::max<char,char,int>('a',100) << std::endl; return 0; }
No comments:
Post a Comment