【问题标题】:Template specialization and inheritance模板特化和继承
【发布时间】:2013-06-08 00:56:01
【问题描述】:

假设我有一个包含很多函数的模板类,我想对它们进行专门化,只更改其中的一部分,而让其他的完全按照基本模板类中的规定进行。

我该怎么做?

以下是我想要实现的目标,但解决方案并不好,因为它不允许我将 int 的专业化称为 Base<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()

【问题讨论】:

    标签: c++ templates inheritance c++11


    【解决方案1】:

    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
    

    演示here.

    【讨论】:

    • 你确定这是标准 C++ 还是编译器扩展?
    • @NicolBolas 我自己一直认为这是完全有效的(并且想知道为什么它不是马上的最佳答案),但这并不意味着什么(不过,我想记住曾经在 Vandevoorde-Josuttis 中明确搜索过,并找到了它)。
    • @NicolBolas 我相信§14.7.3/14 允许这样做。我错了吗?
    【解决方案2】:

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

    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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-19
        • 1970-01-01
        相关资源
        最近更新 更多