0

当我在阅读《C++ Primer》(第4版)第16.1章时,有一个简单的模板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;
}

main函数中的调用:

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.

希望这能帮助像我这样在模板上苦苦挣扎的人。

4

2 回答 2

2

您当前正在比较指针的值,而不是将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);
};
于 2013-02-19T17:24:30.183 回答
1

您的代码与原始代码之间的区别在于类型推断为T. 在最初,他们将std::string对象传递到compare(). 您正在传递 type 的字符文字,它const char[]会衰减到const char*模板参数推导中。

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

于 2013-02-19T17:25:24.983 回答