玩命加载中 . . .

16.3-重载与模板


template<typename T>
string debug_rep(const T& t) {  // const引用版本
    ostringstream ret;
    ret << t;
    return ret.str();
}

template<typename T>
string debug_rep(T *p) {    // 指针版本
    ostringstream ret;
    ret << "pointer: " << p;
    if (p) {
        ret << " " << debug_rep(*p);
    }
    else {
        ret << " null pointer";
    }
    return ret.str();
}

如果传递一个非指针对象,那肯定会调用第一个版本

string s("hi");
cout << debug_rep(s) << endl;   // 输出hi

如果传递的是指针,则两个版本都是可行的

string *p = &s;
debug_rep(p);

debug_rep(const string*&);  // T推断为string*
debug_rep(string*);         // T推断为string

由于第一个版本需要进行普通指针到const指针的转换,所以应该选择第二个版本

现在考虑传入一个指向常量的指针

const string *sp = &s;

两个版本同样都是可行的

debug_rep(const string*&);  // T推断为string*
debug_rep(const string*);   // T推断为const string*

但编译器选择第二版,原因是第二版更特别,只能用于指针类型,而第一版更通用,可以应用于任何类型

当有多个重载模板对一个调用提供同样好的匹配时,应选择更特例化的版本

现在如果有一个非模板的版本

string debug_rep(const string& s) {
    return '"' + s + '"';
}

string s("hi");
cout << debug_rep(s) << endl;

调用时同样有两个可行的版本

debug_rep<string>(const string&);   // T推断为string
debug_rep(const string&);   // 普通非模板函数

则编译器会选择非模板函数的版本

对于一个调用,如果一个非函数模板与一个函数模板提供同样好的匹配,则选择非模板版本

如果传递的是一个字符串字面常量

cout << debug_rep("hi world!") << endl; // 调用debug_rep(T*)

三个版本都是可行的

debug_rep(const char[10]&); // T推断为char[10]
debug_rep(const char*);     // T推断为const char
debug_rep(const string&);   // 需要将const char*转换为string

两个函数模板都是精确匹配的,第二个版本虽然需要将数组转换为指针,但这也是精确匹配。非模板版本需要类型转换,就不是精确匹配。所以,还是调用函数模板的第二个版本,因为其更特例化


文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录