Thursday, February 16, 2012

Overloading Function Templates


Hello everybody

So far, we should have a bit idea of templates programming. In this post I'll speak about overloading functions center of attention to templates.

For a change, I follow using max function.


#include <iostream>
namespace mySpace{
    inline const int& max (const int& a, const int& b){
        std::cout << "int"<< std::endl;
        return a>b?a:b;
    }
template < class T >
   inline T max (const T& a, const T& b){
    std::cout << "template"<< std::endl;
        return a>b?a:b;
    }
template < class T >
   inline T max (const T& a, const T& b, const T& c){
           std::cout << "template, 3: "<< std::endl;
        return max(max(a,b),c);
    }
}
int main(){
    // calls the template with three arguments
    //and this one will call the non-template int function (by argument deduction)
    //because the better choise that compiler can make
    mySpace::max(2, 1, 9);
 
    //both types match perfectly, so calls non-template int (by argument deduction)
    mySpace::max(3, 5); 
 
    // if the template can generate a better match, will be selected
    // there is neither a function with char arguments nor template, so
    // the call will be max<char> (by argument deduction)
    mySpace::max('a', 'b'); 
 
    // calls max<double> (by argument deduction)
    mySpace::max(3.2, 5.4); 
 
    // forcing the call template with no deduction
    // calls max<double> (no argument deduction)
    mySpace::max<double>(7, 42); 

    // calls the nontemplate for two ints
    mySpace::max('a', 42.7); 

    // calls max<int> (by argument deduction)
    // with <>, we are calling the template function
    // rather that a non-template exists
    mySpace::max<>(7, 42); 
 
        return 0;

}

Up to now it seems easy, what happends wheter we start using pointers and char types.
I like to be practical, so let's see another one:

#include <iostream>
#include <cstring>
#include <string>
namespace mySpace{ 
    template < class T > 
    inline const T& max (const T& a, const T& b){ 
        std::cout << "template"<< std::endl;
        return a>b?a:b; 
    }
    template < class T > 
    //I have changed the argument types to constants because I want to pass it by reference, (&)
    //note that const T& is equivalent to T const&
    inline T* const&  max (T* const& a, T* const&  b){ 
        std::cout << "template pointer: "<< std::endl;
        return a>b?a:b; 
    }
    
    //a fuction for C-string, char*
    /*
     * Note: Go back and remember the first template max; I didn't 
     * show any call like max("abc","acd"), this one is deduced as 
     * a char*, so, with the implementations we did (return a>b?a:b;),
     * this operacion is comparing the pointers and no his values
     * so this was a bug
     * 
     * In order to resolve it, we may call max<std::string>("abc","acd")
     * or calling constructor like std::string: max(std::string("abc"),std::st     * ring("acd") )
     * 
     * Or with the following function
     */
    //
    inline char const* const&  max (char const* const& a, char const* const&  b){ 
        std::cout << "c-string: "<< std::endl;
        return (std::strcmp(a,b) < 0) ? b : a;
    }
}
int main(){
    int a = 5, b = 10;
    int* p_a = &a;
    int* p_b = &b; //pointers_to
    
    mySpace::max(a,b); //template
    mySpace::max(p_a,p_b); //template pointer
    mySpace::max(*p_a,*p_b); //template

    char const* s2 = "I'm so cool";
    char const* s1 = "David";
    mySpace::max(s1,s2); //c-string
    mySpace::max<>(s1,s2); //template, the output is David, WRONG!
    mySpace::max("asd","asdasd");//c-string
    
    std::string s3 = "David";
    std::string s4 = "I'm so cool";
    mySpace::max(s3,s4);//c-string
    
    //This is more typical in C
    char* s5 = "David";//warning: deprecated conversion from string constant to ‘char*’
    char* s6 = "I'm so cool";//warning: deprecated conversion from string constant to ‘char*’
    
    //warning: deprecated conversion from string constant to ‘char*’
    //our function works with char const*, so call templates,
    //and how templates are constants this make a warning
    //but note that call can be wrong
    mySpace::max(s5,s6);//template

    return 0;
}

    
Note that I declared all templates as const and by reference, is a good practice to do unless you need to modify.
That's all today, next I will do a bit example with char const* using 3 parameters, like first exercice.

No comments:

Post a Comment