【问题标题】:Function Template Specialization using Base Class使用基类的函数模板特化
【发布时间】:2014-02-04 21:03:59
【问题描述】:

我环顾四周,并没有找到我要找的东西。基本上我想要一个由基类专门化的函数模板。我不知道如何使它使用专门的功能。

意思...

class IBase
{
public:
    virtual std::string func() const = 0;
};

class MyClass : public IBase
{
public:
    std::string func() const { return "From MyClass"; }
};

template <class T>
std::string get_func(const T* t)
{
    return "Unknown";
}

template <>
std::string get_func<IBase>(const IBase* t)
{
    return t->func();
}

int main()
{
    int a;
    MyClass b;

    get_func(&a); // <- Returns 'Unknown'. Good.
    get_func(&b); // <- Returns 'Unknown'. Bad, want 'From MyClass'.
}

我之所以使用const T* 是因为IBase 是抽象的。

【问题讨论】:

  • 请始终为您的问题添加语言标签。这也启用(自动)语法突出显示。
  • 通常,您不想专门化函数模板,而是重载它。在您的情况下,这也可以解决问题:如果为函数调用的参数推导的类型与您专门使用的类型完全匹配,则使用该专门化。
  • 是的。另一方面,函数模板比​​函数重载更严格。有些事情你可以用函数模板做,但不能用重载。

标签: c++ templates template-specialization function-templates


【解决方案1】:

只需使用重载函数即可。

std::string get_func(const IBase *t) {
    return t->func();
}

重载的函数总是在模板之前被选中。

【讨论】:

  • 是的。我需要的是重载函数,而不是模板专业化。
【解决方案2】:

在接受的答案中使用函数重载来替换函数模板特化并不总是一个好主意。对于问题中的示例代码,函数重载不能提供为非专业类打印“未知”的默认实现。函数重载不足的其他示例包括元组和几乎任何可变参数编程。

有问题的代码不起作用的主要原因是目前,类型推导和转换不能很好地相互配合。您需要将 &amp;b 转换为指向其父类(即 IBase*)的指针类型,这是专用函数所期望的。由于当前C++中存在这个问题,需要通过使用来帮助编译器。

get_func((const IBase*)&b);

其次,加virtual可能会更好

std::string func() const { return "From MyClass"; } 

,因为 IBase::func 被定义为一个虚成员函数。 (并非所有编译器都需要这样做:C++ "virtual" keyword for functions in derived classes. Is it necessary?)。

通过这些更改,下面的代码会输出预期的结果:

Unknown
From MyClass

代码:

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

class IBase
{
public:
    virtual std::string func() const = 0;
};

class MyClass : public IBase
{
public:
    virtual std::string func() const { return "From MyClass"; }
};

template <class T>
std::string get_func(const T* t)
{
    return "Unknown";
}

template <>
std::string get_func<IBase>(const IBase* t)
{
    return t->func();
}

int main()
{
    int a;
    MyClass b;

    cout << get_func(&a) << endl; // <- Returns 'Unknown'. Good.
    cout << get_func((const IBase*)&b) << endl; // 
}

【讨论】:

  • 如果您真的需要将函数模板专门化,最好使用 Herb Sutter 在下面文章中讨论的技术,您可以让函数将功能委托给模板类那更容易专业化。通常,仅使用重载可以更快,更清洁地完成工作。见gotw.ca/publications/mill17.htm
  • 同意。该技术甚至比 func 模板更强大。我正在使用 func 模板,因为它更短更接近 OP
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 2011-06-27
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多