【问题标题】:C++ - Is there a way for a template class specialization to contain code from the general template?C++ - 有没有办法让模板类专业化包含来自通用模板的代码?
【发布时间】:2017-11-17 23:08:20
【问题描述】:

给定一个 C++ 类:

template<typename T>
class A {
public:
    int a;
    T x;
    int getA() {return a;}
};

模板特化是否可以从 A 中“继承”(没有实际的 C++ 继承)成员,例如 a 和 getA()?此外,当编写为类执行大量模板特化的代码时,我应该多次键入相同的代码(这有点违背模板的全部目的),还是重组类以适应特化(例如,通过封装另一个模板类成员,因此特化仅限于该类)?

【问题讨论】:

  • 首先,您自己部分回答了这个问题,他说“重组类以使其适应专业化(例如,通过在内部封装另一个模板类成员,以便专业化仅限于该类) ”。其次,继承有没有问题?将通用代码放在基类中对我来说似乎是个好主意。
  • 我只是想问是否有另一种方法只使用模板并且不需要额外的类。当然,其他想法也不错,但学习不同的选择会增加灵活性。 :)
  • 问题是你需要一个类的接口片段成为另一个类的一部分,所以这正是继承的用例。我不认为有另一种方法不是非常复杂来实现它。偏专精呢?即使您必须重写某些成员,您也会这样做一次而不是 N 次。

标签: c++ templates template-specialization


【解决方案1】:

模板特化是否可以从 A 中“继承”(没有实际的 C++ 继承)成员,例如 a 和 getA()?

简短回答:不。

长答案:不,A 是一个类模板,因此您不能从中继承成员(数据或函数)。
此外,您所要求的听起来像 - 我如何才能打败专业化的全部目的?。好吧,从基类继承不依赖模板参数的成员。这是执行此操作的更直接的方法以及该语言为您提供的功能。

您不能只继承一个类型的成员函数而不扩展该类型。
有很多技术可以达到目的:直接继承、mixin、inherit-from-above idiom等等。
它们都通过继承来compose 接口。我不明白为什么要妖魔化它。

【讨论】:

  • 虽然同意它的一般含义,但我不同意“为不依赖模板参数的成员从基类继承”这一点,为什么会有这样的限制? OP只是想继承一些东西,然后继承可以实现这一点,无论是种类的继承(模板与否)。
【解决方案2】:

如果你不想要额外的课程,那么你可以像下面这样欺骗一点:

template <class T>
class A {
public:
        void f() { cout << "here" << endl; }
};

template <> class A<char> : private A<A<char> >  {
public:
        using A<A<char> >::f;
};

当然希望能够编写template &lt;&gt; class A&lt;char&gt; : private A&lt;char&gt; 并获得从泛型案例继承的特化,但这是不可能的,所以我使用了一种技巧来实例化具有某种类型的泛型案例(这里类似于CRTP,但可以使用任何其他类型)。

另一个技巧是使用第二种类型和默认值。

【讨论】:

    【解决方案3】:

    我找到了办法:

    #include <type_traits>
    
    typedef void**const*const** dummy;
    
    // Generic template
    template <typename T1, typename T2 = dummy>
    class A {
        static_assert(std::is_same<T1,dummy>::value || std::is_same<T2,dummy>::value,
                      "too many template arguments for class template 'A'");
        typedef typename std::conditional<std::is_same<T1,dummy>::value, T2, T1>::type T;
        public:
            int a;
            T x;
            int getA() {return a;}
    };
    
    // Specialization for int
    template <typename X>
    class A<int,X> : public A<X,int> {
        public:
            void foo() {}
    };
    

    类模板 A 仅使用一个模板参数进行实例化。当 A 被实例化为除 int 以外的任何类型时,正如预期的那样,它具有泛型的所有成员。当 A 用 int 实例化时,它不仅有特化的成员,还有泛型的成员。

    【讨论】:

      猜你喜欢
      • 2013-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      相关资源
      最近更新 更多