Reputation: 64
When I am reading "C++ Primer" (4th Edition) Chapter 16.1, there is a simple template demo:
// 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;
}
the invocation in main function:
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;
}
I made several modifications over this piece of code:
//----------------------------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----------------
there is a problem when I compile and run it:
under VS2008, it gives:
String 1 : A
String 2 : a
A > a
A > a
under g++ (Debian 4.4.5-8) 4.4.5, it gives:
String 1 : A
String 2 : a
A < a
A < a
the correct answer is **A<a**
.
However, when I comment out the following:
cout << "String 1 : " << "A" << endl;
cout << "String 2 : " << "a" << endl;
under VS2008, it gives:
String 1 : A
String 2 : a
A < a
A < a
under g++ (Debian 4.4.5-8) 4.4.5, it gives:
String 1 : A
String 2 : a
A > a
A > a
the compile command is as following:
g++ test.cpp -o test -Wall -O0
I want to know why this could happen? Is the problem (A?B:C) expression that I have used incorrectly? It seems that my code is correct. It has bothered me for days. Any help would be appreciated.
Case Closed!
I replaced the myCompare() invocation by the following:
iRes=myCompare(static_cast<string>("A"), static_cast<string>("a"));
It works. No matter how I change the context, it always gives the right answer. I should have been aware that I am comparing two const char*
, I give it a try just to be sure about it.
The lesson that I learned here is that this template could be instantiated into two functions:
int compare(const char* &v1, const char* &v2); // two pointers
int compare(const string &v1, const string &v2); // two objects
Thanks for all the help that you guys offered. Really appreciated! Have a good day!
Additional info.
I added a simple express in the myCompare function:
cout<<"the type is : "<<typeid(T).name() <<endl;
this gives clear type information about what kind of type that T has been instantiated. the whole code is as following:
//----------------------------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----------------
this results of this program is:
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
Notice that:
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.
Hope this would help someone like me who is struggling with templates.
Upvotes: 0
Views: 607
Reputation: 171127
The difference between your code and the original is the type deduced as T
. In the original, they're passing std::string
objects into compare()
. You're passing character literals, which are of type const char[]
, which decays into const char*
on template argument deduction.
In other words, your function ends up comparing the literals' addresses, not their contents.
Upvotes: 1
Reputation: 4207
You are currently comparing the values of the pointers, rather than considering const char *
as a string, which is nearly never what you want. If you want to compare const char *
as std::string
s, you should specialise your template.
template<>
int myCompare(const char *const &v1, const char *const &v2){
return myCompare<std::string>(v1, v2);
};
Or perhaps, call strcmp
in that case,
template<>
int myCompare(const char *const &v1, const char *const &v2){
return strcmp(v1, v2);
};
Upvotes: 2