模板特化和继承

35

假设我有一个拥有许多函数的模板类,我想对其中的一些函数进行特化,但仍保持其他函数与基础模板类中指定的完全相同。

我该如何实现这个目标?

下面是我想要实现的内容,但解决方案并不好,因为它不能让我使用 Base<int> 来引用 int 的特化版本 - 我需要使用 IntSpec 来代替。

#include <iostream>

using namespace std;

template<typename T>
struct Base
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

struct IntSpec : public Base<int>
{
  void print2() {cout << "Base<int>::print2()" << endl;};
};

int main()
{
  Base<double> d;
  // Base<int> i;  <-- I want this kind of instantiation
  IntSpec i;

  d.print1();
  d.print2();
  i.print1();
  i.print2();
}

输出结果为:

Base::print1
Base::print2
Base::print1
Base<int>::print2()
3个回答

47

Nicol的解决方案很好,但这是另一种选择:

template<typename T>
struct Base
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

template<>
void Base<int>::print2() {cout << "Base<int>::print2()" << endl;};
那么您就可以专门化只特定的成员函数,并且仍然使用那些您没有专门化的函数(在这种情况下,是print1),而不会有任何问题。因此,现在您可以像您想要的那样使用它:
Base<int> i;
i.print1();
i.print2(); // calls your specialization

点击这里查看演示。


2
你确定那是标准的C++,还是编译器的扩展? - Nicol Bolas
@NicolBolas 我个人一直认为这是完全有效的(并想知道为什么它不是最佳答案),但这并不意味着什么(尽管我记得曾经在 Vandevoorde-Josuttis 中明确搜索过这个问题,并找到了答案)。 - Christian Rau
4
我相信 §14.7.3/14 允许这样做。我错了吗? - mfontanini
1
不幸的是,当您的模板类具有多个参数且您想为其中一个参数专门化方法时,此解决方案无效。 - Arnaud Mégret

29

你只需要使用两个模板类:

template<typename T>
struct CommonBase
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

template<typename T>
struct Base : public CommonBase<T>
{
};

template<>
struct Base<int> : public CommonBase<int>
{
  void print2() {cout << "Base::print2" << endl;};
};

你始终使用Base,而不是CommonBase


4
另一种解决方案是在您想要重新定义的函数中添加一个间接层,即:

另一种解决方案是在您想要重新定义的函数中添加一个间接层,即:

template<typename T>
struct foo
{
    template<typename T2>
    void bar_impl()
    {
        //generic function
    }

    void bar()
    {
        bar_impl<T>();
    }
};

然后你可以针对每种类型单独专门化每个函数,或者根据需要专门化整个类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接