C++ 入门第 5 版。函数模板重载

Mae*_*tro 6 c++ template-argument-deduction function-templates-overloading

C++ Primer一书中,有一个关于函数模板重载的例子:

// print any type we don't otherwise handle
template <typename T> string debug_rep(const T &t)
{
    cout << "debug_rep(T const&)\n";
    ostringstream ret; // see § 8.3 (p. 321)
    ret << t; // uses T's output operator to print a representation of t
    return ret.str(); // return a copy of the string to which ret is bound
}

// print pointers as their pointer value, followed by the object to which the pointer points
// NB: this function will not work properly with char*; see § 16.3 (p. 698)
template <typename T> string debug_rep(T *p)
{
    std::cout << "debug_rep(T*)\n";
    ostringstream ret;
    ret << "pointer: " << p << '\n';         // print the pointer's own value
    if (p)
        ret << " " << debug_rep(*p); // print the value to which p points
    else
        ret << " null pointer";      // or indicate that the p is null
    return ret.str(); // return a copy of the string to which ret is bound
}
Run Code Online (Sandbox Code Playgroud)

如果我们用一个指针调用 debug_rep:

cout << debug_rep(&s) << endl;
Run Code Online (Sandbox Code Playgroud)

这两个函数都会生成可行的实例化:

  • debug_rep(const string* &),这是 debug_rep 的第一个版本的实例化,T绑定到string*

  • debug_rep(string*),这是debug_repT绑定到的第二个版本的实例化string*

第二个版本的实例化debug_rep与此调用完全匹配。

第一个版本的实例化需要将普通指针转换为指向 的指针const。正常的函数匹配说我们应该更喜欢第二个模板,实际上这就是运行的模板。

但是,如果我将指向字符串的指针声明为const虽然没有转换,则始终选择第二个版本:

    string const s("hi"); // const
    cout << debug_rep(&s) << '\n';
Run Code Online (Sandbox Code Playgroud)

所以我认为这是书中的一个错误,我认为因为版本采用指针是首选,因为我们传递了一个指针beconst或 not (T将被推导出为std::string const*or std::string*)。

你怎么认为?

eca*_*mur 5

书错了。

在第一个示例中,生成的实例化不是debug_rep(const string* &),而是debug_rep(string* const&)。也就是说,const限定指针,而不是指向的东西。(如果本书使用了正确的 const,这会更明显;也就是说,template <typename T> string debug_rep(T const& t)对于第一个函数模板。)

确实,T并且T const&与函数模板重载具有相同的优先级;在它们形成重载集的地方,它将是模棱两可的。之所以T*被选中,T const&是因为它更专业;简单地说,任意T*值可以传递给函数taking T const&,而任意T const&值不能传递给函数taking T*

  • @DanielLangr 当然!如果函数模板被重载,并且没有非模板可行的函数,而只有同样良好匹配的模板版本,则通过函数匹配选择更专门的版本,否则调用是不明确的。 (2认同)