【问题标题】:C++ primer 5th ed. function template overloadingC++ 入门第 5 版。函数模板重载
【发布时间】:2020-12-10 21:29:54
【问题描述】:

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
}

如果我们用指针调用 debug_rep:

cout << debug_rep(&s) << endl;

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

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

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

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

第一个版本的实例化需要将普通指针转换为指向const 的指针。正常函数匹配表明我们应该更喜欢第二个模板,而且确实是运行的那个。

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

    string const s("hi"); // const
    cout << debug_rep(&s) << '\n';

所以我认为这是本书中的一个错误,我认为因为版本需要一个指针是首选,因为我们传递的指针是否为constT 将被推断为std::string const*std::string* )。

你怎么看?

【问题讨论】:

  • C++ Primer 的哪个版本?

标签: c++ template-argument-deduction function-templates-overloading


【解决方案1】:

书错了。

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

确实,TT const&amp; 与函数模板重载具有相同的优先级;它们形成重载集的地方将是模棱两可的。选择T* 而不是T const&amp; 的原因是它更专业;简单地说,一个任意的T* 可以传递给一个采用T const&amp; 的函数,而一个任意的T const&amp; 不能传递给一个采用T* 的函数。

【讨论】:

  • 这种解释我的问题:godbolt.org/z/T43q34。这是否意味着 more-specialized 概念涉及重载解析? (我希望两个实例都被实例化,然后应用重载解决方案,但这会导致歧义。)
  • @DanielLangr 确定!如果函数模板被重载并且没有非模板可行的函数,但只有同样好的匹配的模板版本,那么函数匹配会选择更专业的一个,否则调用是不明确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2021-09-04
  • 1970-01-01
  • 2021-08-25
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多