Перегрузка функции шаблона. Понимание символа - PullRequest
3 голосов
/ 06 июня 2019

У меня есть простой код, который сравнивает пару значений. Я использую шаблонную функцию, чтобы уменьшить количество кода, поэтому я перегружал функцию дважды (для разных случаев).

    //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;
        }  

Мой вывод:
0
1
1 * * +1010 1
0
0
1
И я ожидал:
0
1
0
1 * * тысяча двадцать-один 0
0
1

Почему это показывает, что две строки идентичны? Почему, если я полностью поменяю слово, скажем

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

тогда только это дает правильный результат. Разве моя вторая перегруженная функция не должна обрабатывать это правильно? (bool cmp(T *x,T *y))

Ответы [ 2 ]

3 голосов
/ 06 июня 2019

Почему это показывает, что две строки идентичны?

Поскольку

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

проверяет только значение first , указанное xи y.

Поэтому при проверке

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

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

убедитесь, что h равно h.

Если вы хотите проверить равенство между строками(и если вы хотите избежать использования старого доброго std::strcmp()), вы должны проверять все символов до первого нуля.

Но это верно для C-строки старого стиля;Я не думаю, что это хорошая идея, чтобы разработать функцию, которая проверяет равенство между указателями для универсального типа T.

- EDIT -

Не могли бы вы наставить меня, пожалуйста

Чтобы привести пример ... я не думаю, что в простом C много времени, но что-то следующее должно работать

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

   return *p1 == *p2;
 }

Не по теме: вы пишете код как

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

Это эквивалентно

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

В более общем смысле ... если у вас есть код типа

if ( someTest )
   return true;
else
   return false;

и функция, возвращающая bool (или someTest типа bool), вы можете написать (и, ИМХО, более читабельно и элегантно) просто написать

return someTest;
1 голос
/ 06 июня 2019

Почему это показывает, что две строки идентичны?

Массив затухает до указателя, поэтому char taChars[6] будет использовать перегрузку template <class T> bool cmp(T *x,T *y) и сравнивает только первый элемент (который в вашем случае равен).

В C ++ 17 вы можете сделать:

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;
    }
}

Демо

...