0

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.

9
  • I know that strcmp() function would work, however, I think the string object has reloaded the relation operator. Commented Feb 19, 2013 at 17:20
  • 1
    std::string yes, but "A" isn't a string, it's const char*. Commented Feb 19, 2013 at 17:21
  • *overloaded operator< Commented Feb 19, 2013 at 17:21
  • 6
    You're comparing const char*s, good job. Commented Feb 19, 2013 at 17:21
  • 1
    Your version is much less readable than the original, and no more/less efficient. Furthemore, using namespace std should be banned. Commented Feb 19, 2013 at 17:21

2 Answers 2

2

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::strings, 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);
};
Sign up to request clarification or add additional context in comments.

Comments

1

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.

1 Comment

@GManNickG Thanks for the edit, I was typing a little too quickly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.