Неожиданный вывод при сравнении строк - PullRequest
0 голосов
/ 03 февраля 2020

В следующем коде CPP функция isGreater() выполняет свою работу для целых чисел. Тем не менее, он не дает правильный результат для строк. Сначала я предполагал, что метод std:: string ::compare() не использовался, поэтому я создал специальный шаблонный метод isGreater() для строк, и сначала cout по-прежнему выдает результат как 1. Я считаю, что он должен сравнивать строки в алфавитном порядке. Но я не думаю, что это делает это. Вторые и третьи операторы cout обеспечивают правильный вывод, т.е. целые числа в сравнении и строки в алфавитном порядке. Что именно происходит в isGreater() для строк?

#include <iostream>
#include <string>
using namespace std;

template <typename T>
bool isGreater(T x1, T x2)
{
    return (x1 > x2);
}

template <>
bool isGreater(string x1, string x2)
{
    return (x1.compare(x2));
}

int main()
{
    cout << isGreater("AAAA", "ZZZZ") << endl; //First cout
    cout << isGreater(5, 10) << endl; //Second cout
    string str1 = "AAA";
    string str2 = "ZZZZZ";
    cout << str1.compare(str2) << endl; //Third cout
    return 0;
}

Ответы [ 3 ]

4 голосов
/ 03 февраля 2020

Проблема в том, что isGreater("AAAA", "ZZZZ") не вызывает вашу std::string специализацию. Он вызывает общую шаблонную функцию, используя указатели (const char*), и вы сравниваете эти указатели вместо строк.

Вам необходимо добавить специализацию (или перегрузку), принимающую аргументы указателя если вы хотите использовать буквенные строки.


Что касается специализации std::string, функция std::string::compare не возвращает то, что вы думаете делает.

Возвращает «истинное» (ненулевое) значение, если строки не равны, которое может быть отрицательным (и ненулевое значение будет истинным), если x1 меньше x2. Либо используйте стандарт больше, чем оператор (который перегружен ), либо проверьте, что возвращаемое значение больше нуля:

return x1.compare(x2) > 0;
1 голос
/ 03 февраля 2020

Как указано в других ответах, вы не вызываете специализацию std :: string, так как у вас нет std::string, у вас есть const char [].

Лучшее решение - это убедитесь, что шаблонный метод не заменит специализацию. Начиная с C ++ 17 я буду использовать if constexpr, в C ++ 11 и C ++ 14 я буду использовать std::enable_if. (Обратите внимание, что я использую string_view для предотвращения выделения памяти.)

template <typename T>
bool isGreater(T x1, T x2)
{
if constexpr (std::is_convertable_v<T, std::string_view>)
    std::string_view{x1}.compare(x2);
else
    return (x1 > x2);
}

Старые стандарты:

template <typename T, typename = std::enable_if<!std::is_convertable<T, std::string>::value>::type>
bool isGreater(T x1, T x2)
{
    return (x1 > x2);
}

bool isGreater(string x1, string x2)
{
    return (x1.compare(x2));
}
0 голосов
/ 03 февраля 2020
#include <iostream>
#include <string>
using namespace std;

template <typename T>
bool isGreater(T x1, T x2)
{
    return (x1 > x2);
}

bool isGreater(string x1, string x2)
{
    return (x1.compare(x2));
}

int main()
{
    cout << isGreater(string("AAAA"), string("ZZZZ")) << endl;
    cout << isGreater(5, 10) << endl;
    string str1 = "AAAA";
    string str2 = "ZZZZ";
    cout << str1.compare(str2) << endl;
    return 0;
}

Вам нужно набрать приведение, иначе он вызывает шаблон

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...