Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template function overloading. Understanding char

I have a simple code that compares couple values. I'm using template function to reduce the amount of code, so i overloaded function twice(for different cases).

    //cmp.h
        template <class T>
        bool cmp(T x,T y)
        {
           if(x == y)
           { 
           return true;
           }else
           return false;
        }

        template <class T>
bool cmp(T *x,T *y)
{
   if(*x==*y)
   { return true;}else
   return false;
}


        //main.cpp  
        #include <iostream>
        #include <string>
        #include "cmp.h"
        using std::cout;
        using std::endl;
        using std::string;
        int main() {
             int aInt = 1, bInt = 2;
             double aDouble = 3.0, bDouble = 3.0;
             char aChars[5] = "haha", bChars[5] = "hahb";
             char taChars[6] = "trick", tbChars[6] = "trick";
             string aStr = "haha", bStr = "aha";
             int* aIntPtr = &aInt, *bIntPtr = &bInt;
              cout << cmp(aInt, bInt)<< endl;
             cout << cmp(aDouble, bDouble)<< endl;
              cout << cmp(aChars, bChars)<< endl;//i can't figure out why char prints out true here ???
             cout << cmp(taChars, tbChars)<< endl;
             cout << cmp(aStr, bStr)<< endl;
             cout << cmp(aIntPtr, bIntPtr)<< endl;
             cout << cmp(&aDouble, &bDouble) << endl;
             return 0;
        }  

My output is:
0
1
1
1
0
0
1
And i expected:
0
1
0
1
0
0
1

Why it shows that two strings are identical ? Why if i entirely change the word, lets say

char aChars[5] = "jack", bChars[5] = "hahb";  

then only it gives the right result. Isn't my second overloaded function should handle this right? (bool cmp(T *x,T *y))

like image 662
casper Avatar asked Nov 23 '25 13:11

casper


2 Answers

Why it shows that two strings are identical ?

Because

template <class T>
bool cmp(T *x,T *y)
{
   if(*x == *y)
   { 
   return true;
   }else
   return false;
}  

check only the first value pointed by x and y.

So when you check

 char aChars[5] = "haha", bChars[5] = "hahb";

 cout << cmp(aChars, bChars)<< endl;//

check that h is equal to h.

If you want check the equality between strings (and if you want avoid the use of the good-old std::strcmp()) you have to check all characters until the first zero.

But this is true for old style C-string; I don't think it's a good idea to develop a function that check equality between pointer for a generic type T.

-- EDIT --

Could u guide me please

To give an example... it's a lot of time that I don't think in plain C but something as follows should works

bool cmp (char const * p1, char const * p2)
 {
   for ( ; *p1 && *p1 == *p2 ; ++p1, ++p2 )
    ;

   return *p1 == *p2;
 }

Off Topic: you write code as

bool cmp(T *x,T *y)
{
   if(*x==*y)
   { return true;}else
   return false;
}

It's equivalent to

bool cmp(T *x,T *y)
 { return *x == *y; }

More generally speaking... if you have a code of type

if ( someTest )
   return true;
else
   return false;

and the function return a bool (or someTest is of type bool), you can write (and, IMHO, is more readable and elegant) simply write

return someTest;
like image 185
max66 Avatar answered Nov 26 '25 04:11

max66


Why it shows that two strings are identical ?

Array decays to pointer, so char taChars[6] will use overload template <class T> bool cmp(T *x,T *y) and so compare only first element (which are equal in your case).

In C++17, you might do:

template <typename T>
bool cmp(const T& lhs, const T& rhs)
{
    if constexpr (std::is_pointer<T>::value) {
        return *lhs == *rhs;
    } else if constexpr (std::is_array<T>::value) {
        return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs));
    } else {
        return lhs == rhs;
    }
}

Demo

like image 39
Jarod42 Avatar answered Nov 26 '25 02:11

Jarod42



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!