C ++ неправильное использование шаблона или проблемы сравнения литералов строк компиляторов с шаблоном

Когда я читаю «C ++ Primer» (4-е издание) главу 16.1, есть простая демонстрационная модель:

// implement strcmp-like generic compare function
// returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller
template <typename T>
int compare(const T &v1, const T &v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}

вызов в основной функции:

int main ()
{
// T is int;
// compiler instantiates int compare(const int&, const int&)
cout << compare(1, 0) << endl;
// T is string;
// compiler instantiates int compare(const string&, const string&)
string s1 = "hi", s2 = "world";
cout << compare(s1, s2) << endl;
return 0;
}

Я сделал несколько модификаций над этим фрагментом кода:

//----------------------------test.cpp start----------------
#include <iostream>
#include <string>

using namespace std;

template<class T>
int myCompare(const T &v1, const T &v2){
cout << v1 << " " << ((v1 > v2) ? (">") : ((v1 < v2) ? ("<") : ("="))) << " " << v2 << endl;
return (v1 > v2) ? (1) : ((v1 < v2) ? (-1) : 0);
};

int main(void) {
int iRes;
cout << "String 1 : " << "A"<<endl;
cout << "String 2 : " << "a"<<endl;
iRes = myCompare("A", "a");
cout << "A " << ((iRes == 1) ? (">") : ((iRes == (-1)) ? ("<") : ("="))) << " a" << endl;
return 0;
};
//----------------------------test.cpp end----------------

есть проблема, когда я компилирую и запускаю его:

под VS2008 это дает:

String 1 : A
String 2 : a
A > a
A > a

под g ++ (Debian 4.4.5-8) 4.4.5 он дает:

String 1 : A
String 2 : a
A < a
A < a

правильный ответ **A<a**,

Однако, когда я закомментирую следующее:

cout << "String 1 : " << "A" << endl;
cout << "String 2 : " << "a" << endl;

под VS2008 это дает:

String 1 : A
String 2 : a
A < a
A < a

под g ++ (Debian 4.4.5-8) 4.4.5 он дает:

String 1 : A
String 2 : a
A > a
A > a

команда компиляции выглядит следующим образом:

g++ test.cpp -o test -Wall -O0

Я хочу знать, почему это могло произойти? Является ли проблема (A? B: C) выражением, которое я использовал неправильно? Кажется, мой код правильный. Это беспокоило меня в течение нескольких дней. Любая помощь будет оценена.


Дело закрыто!

Я заменил вызов myCompare () следующим:

iRes=myCompare(static_cast<string>("A"), static_cast<string>("a"));

Оно работает. Независимо от того, как я изменяю контекст, он всегда дает правильный ответ. Я должен был знать, что я сравниваю два const char*Я попробую, чтобы быть уверенным в этом.

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

int compare(const char* &v1, const char* &v2);     // two pointers
int compare(const string &v1, const string &v2);   // two objects

Спасибо за всю помощь, которую вы, ребята, предложили. Очень ценится! Хорошего дня!


Дополнительная информация.

Я добавил простой экспресс в функцию myCompare:

cout<<"the type is : "<<typeid(T).name() <<endl;

это дает четкую информацию о типе того, какой тип экземпляра T был создан.
весь код выглядит следующим образом:

//----------------------------test.cpp start----------------
#include <iostream>
#include <string>
#include <typeinfo>

using namespace std;

template<class T>
int myCompare(const T &v1, const T &v2){
cout<<"the type is : "<<typeid(T).name() <<endl;
cout<<v1<<" "<<((v1>v2)?(">"):((v1<v2)?("<"):("=")))<<" "<<v2<<endl;
return (v1>v2)?(1):((v1<v2)?(-1):0);
};

int main(void){
int iRes;
iRes=myCompare(1234, 3);
iRes=myCompare("test","poor");
iRes=myCompare(static_cast<string>("test"),static_cast<string>("poor"));
iRes=myCompare(21.23,4.0);
return 0;
};

//----------------------------test.cpp end----------------

это результаты этой программы:

the type is : i
1234 > 3
the type is : A5_c
test > poor
the type is : Ss
test > poor
the type is : d
21.23 > 4

Заметить, что:

1, #include <typeinfo> should be included.
2, the second comparison is incorrect, it simply compares the addresses of the constant char array rather than string stored in the constant char array.

Надеюсь, что это поможет кому-то вроде меня, кто борется с шаблонами.

0

Решение

В настоящее время вы сравниваете значения указателей, а не рассматриваете const char * как строка, которая почти никогда не то, что вы хотите. Если вы хотите сравнить const char * как std::strings, вы должны специализировать свой шаблон.

template<>
int myCompare(const char *const &v1, const char *const &v2){
return myCompare<std::string>(v1, v2);
};

Или, возможно, позвоните strcmp в таком случае,

template<>
int myCompare(const char *const &v1, const char *const &v2){
return strcmp(v1, v2);
};
2

Другие решения

Разница между вашим кодом и оригиналом заключается в типе, выведенном как T, В оригинале они проходят std::string объекты в compare(), Вы передаете символьные литералы, которые имеют тип const char[]который распадается на const char* на выводе аргумента шаблона.

Другими словами, ваша функция сравнивает адреса литералов, а не их содержимое.

1

По вопросам рекламы [email protected]