在c ++模板特化中添加基类

时间:2013-08-14 09:31:16

标签: c++ templates

在我工作的代码库的尘土飞扬的角落里,我遇到了一个类似于以下的类层次结构:

class Base1
{
  int base1;
};

class Base2
{
  int base2;
};
template <typename T> class A : public Base1
{
      T _specialT;
};
template <> class A<int> : public Base2
{
      int _special;
};

在A的专业化中使用Base2令我感到惊讶。我一直在四处寻找它究竟意味着什么,未能找到任何这种设计的例子或讨论。

在我看来,这样做会导致A从Base1和Base2继承,而非专用的A的其他用途将仅从Base1继承。这让我有几个问题:

  1. 我能理解这一点吗?
  2. 是否有任何非明显的警告 以这种方式添加到层次结构中?你为什么要这样做?
  3. 有时候这会被认为是好的设计吗?

3 个答案:

答案 0 :(得分:4)

  1. 否。主要类模板继承自Base1,只有<int>专门化继承自Base2(仅来自Base2)。
  2. 不知道使用它的上下文,我无法回答2.或3.

    您经常可以在模板元编程中看到从不同类型派生的特化。例如:

    template<typename T, typename U>
    struct is_same : std::false_type {};
    
    template<typename T>
    struct is_same<T,T> : std::true_type {};
    

    这是完全有效的事情。这是否是一件好事完全取决于正在解决的问题。

答案 1 :(得分:2)

从正常情况来看,模板的特化是完全独立的,代码方面的。因此,A<int>不会来自Base1Base2,只能来自Base2

有些情况下,专业化是好的设计。当然,这是不可能从你抽象的例子中得知。

答案 2 :(得分:2)

请记住,类模板的不同实例化是不同的独立类。模板的专业化不会在一般情况下添加内容,而是完全替换它。

因此,A<int>是一个派生自Base2的类,有一个名为_special的int成员,A<double>A<char>是两个独立的不同类两者都碰巧派生自Base1,每个都有一个类型为double和char的成员,分别名为_specialT

所以:

  1. 您的问题似乎是正确理解它。
  2. 有一些警告,特别是如果专业化不是直接定义在基本模板之后,而是定义在另一部分。如果维护者看到A的一般定义并尝试在Base1上使用A<int>的某些方法(或使用_specialT成员),那么会出现编译错误,这会让人感到惊讶他没有看到专业化。一个非常流行的例子是std::vector<bool>在标准中的特殊化,与“普通”std::vector的行为不同,被广泛认为是破碎的。
  3. 有些人可能会考虑这种优秀的设计,有时像很多的人认为这样的设计很好。然而,设计有时候是一种品味问题,当谈到模板及其不那么典型的用例时,很多人会考虑意想不到的事情,比如专业化中的不同基类作为坏风格或者至少是“黑色模板魔术”,例如:当它用于模板元编程时。
  4. 这种模式(源自不同基础的特化)通常用于模板元编程。一个(非常)简单的例子:

    template <class T>
    struct is_int_or_double : std::false_type
    {};
    
    template <>
    struct is_int_or_double<int> : std::true_type //another base class!
    {};
    
    template <>
    struct is_int_or_double<double> : std::true_type //another base class!
    {};