C ++误用模板或编译器的问题字符串字面与模板比较

时间:2013-02-19 17:17:31

标签: c++ string templates comparison literals

当我阅读“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.

希望这会帮助像我一样正在努力学习模板的人。

2 个答案:

答案 0 :(得分:2)

您当前正在比较指针的值,而不是将const char *视为字符串,这几乎不是您想要的。如果您想将const char *std::string进行比较,则应该专门化您的模板。

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

答案 1 :(得分:1)

您的代码与原始代码之间的差异是推导为T的类型。在原文中,他们将std::string个对象传递给compare()。你传递了const char[]类型的字符文字,它在模板参数推导上衰减为const char*

换句话说,您的函数最终会比较文字的地址,而不是它们的内容。