通过引用const char*传递字符串文字无法使用g ++ 4.6.3进行编译

ltu*_*tux 6 c++ templates pointers

这是C++ Primer第4版第16章的一个例子,它是关于模板专业化的.

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

template <class T>
int compare(const T& v1, const T& v2) {
    if(v1<v2) return -1;
    if(v2<v1) return 1;
    return 0;
}

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

int main(int argc, const char *argv[])
{
    cout << compare("abc","defg") << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望compare("abc","defg")能够调用模板的专用版本.但事实是,g ++ 4.6.3将无法编译此代码并给出以下错误:

错误:没有匹配函数来调用'compare(const char [4],const char [5])'

注意:候选者是:template int compare(const T&,const T&)

现在给出以下事实:

I.字符串文字或C++中的C风格字符串实际上是一个const char数组.

II.如果作为普通的非引用类型传递,则数组将被静默地转换为指向其第一个元素的指针.

在这里,我只是传递字符串文字"abc"和"defg"作为参考 const char*,我希望它们将被转换为const char*第一个然后通过引用传递.但似乎g ++不同意我并且拒绝编译代码.

但是如果我用函数重载替换模板特化,那就是替换

template <>
int compare<const char*>(const char* const &v1, const char* const &v2){
    return strcmp(v1,v2);
}
Run Code Online (Sandbox Code Playgroud)

int compare(const char* const& v1, const char* const& v2){
    return strcmp(v1,v2);
}
Run Code Online (Sandbox Code Playgroud)

那么g ++很乐意编译它.

那问题到底在哪里呢?为什么我不能const char* const&在模板特化版本中通过参数类型传递字符串文字 ?

tao*_*ocp 6

以下答案基于来自的解释C++ Templates: The complete guide pp57: Using String literals as Arguments for Function templates.

template <class T>
int compare(const T& v1, const T& v2) {
    if(v1<v2) return -1;
    if(v2<v1) return 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这需要两个参数v1,并v2具有相同的类型.

template <>
int compare<const char*>(const char* const &v1, const char* const &v2){
    return strcmp(v1,v2);
}
Run Code Online (Sandbox Code Playgroud)

这要求您具有const char *类型的参数.

但是,"abc"有类型char const[4]"defg"有类型char const[5].它们是不同的类型.由于专用版本和模板版本都需要参考参数,因此在参数推断期间没有数组到指针的衰减.因此,您不能将不同长度的字符串文字传递给它们以查找匹配项.如果提供常规函数,不需要任何参数推导,编译器将找到匹配项.

如果声明非引用参数,则可以使用不同长度的字符串文字替换它们.这种行为的原因是,在参数推导array-to-pointer转换(通常称为衰减)期间,只有在参数没有引用类型时才会发生.