【问题标题】:Function templates and derived classes函数模板和派生类
【发布时间】:2018-10-16 10:38:10
【问题描述】:

如果是这段代码,为什么foo(d) 调用模板函数而不是'base'函数?有没有办法让它调用基函数而不显式编写另一个函数重载?

template <class T> void foo(T val)
{
    printf("template called\n");
}

class Base
{
};

void foo(const Base &val)
{
  printf("Base called\n");
}

class Derived : public Base
{   
};

int main() {
    Derived d;
    foo(d);
    return 0;
}

【问题讨论】:

  • foo&lt;Derived&gt; 是完全匹配的。您可能 SFINAE 模板功能是您不想重载。
  • 您的非模板 foo() 不完全匹配 - 它需要从 const Derived &amp; 转换为 const Base &amp;)。模板化的 foo() 提供完全匹配 (foo&lt;Derived&gt;())。精确匹配(无需类型转换)优于需要类型转换的匹配。

标签: c++ templates derived-class


【解决方案1】:

为什么foo(d) 调用模板函数而不是'base'函数?

因为模板函数fooT被推导出为Derived,所以是完全匹配的。对于非模板,需要进行派生到基础的转换。

你可以用SFINAE来做;使函数模板仅适用于不是从Base(或Base 本身)派生的类型。

template <class T> 
std::enable_if_t<!std::is_base_of_v<Base, T>> foo(T val)
{
    printf("template called\n");
}

LIVE

【讨论】:

  • 谢谢。对于我的要求,这将导致严重的痛苦,因为我希望使用模板功能作为后备。 SFINAE 意味着模板必须明确知道不能在哪些对象上使用它,这会使依赖关系颠倒过来。我认为常规函数重载对我来说可能是更好的方法。
  • @Roddy 重载方法意味着您必须添加另一个以Derived 作为参数的重载;否则,如您所见,函数模板在重载决议中获胜。
  • 是的,明白了。但是我现在打算完全放弃模板函数,并为以前由模板处理的情况提供显式的重载函数。
猜你喜欢
  • 2014-02-04
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
  • 2016-02-17
  • 2015-04-10
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多