从不同的基类继承的类模板专长是否合法?

时间:2018-07-24 17:21:41

标签: c++ templates inheritance specialization

我遇到了这样的情况,我的类模板部分专业化共享很多代码,将其移入基类是有意义的。但是,对于所有专业而言,拥有相同基类并没有意义。

以下示例代码在GCC 7.1中编译,没有错误:

struct foo_base_1 { void bar() { std::cout << "base 1" << std::endl; }; };

struct foo_base_2 { void bar() { std::cout << "base 2" << std::endl; }; };

template <typename A, typename B>
struct foo { };

template <typename A>
struct foo<A, int> : foo_base_1 { };

template <typename A>
struct foo<A, double> : foo_base_2 { };

int main()
{
    foo<int, int> x;
    foo<int, double> y;

    x.bar();
    y.bar();
}

我意识到,尽管是同一类别的专业,但它们实际上是不同的类型。尽管如此,仍然感到同一类可以从不同的基础继承是错误的。

我想向大家保证这可以。我找不到标准的相关部分,我也不愿意仅仅因为它可以编译就相信它(我之前就被咬过)。

1 个答案:

答案 0 :(得分:5)

每个模板实例化都是其自己的单独类。正如任何普通类都可以从您想要的任何基类继承一样,模板实例化也可以这样做。考虑以下示例:

template <typename Base>
class Derived : public Base
{
};

绝对合法...

例如,这是curiously recurring template pattern的基础。

现在决定是否以与原始/主模板模式不同的方式实现特定的实例化(这样,您可以专长;或者先分组,然后局部),都没关系。

该主题的标准似乎有点短:

  

17.5.1类模板[temp.class]
  1类模板定义了一组无界的相关类型的布局和操作。
  2 [示例:单个类模板列表可能会提供一组无限的类定义:每个类型T的一个类列表,每个类列表都描述了类型T的元素的链接列表。类似地,类模板Array描述一个连续的动态数组的定义可能是这样的:[一些样本模板声明]   前缀模板指定正在声明模板,并且声明中可以使用类型名称T。换句话说,数组是一个以T为参数的参数化类型。   —结束示例]

[由我突出显示],但是稍后在定义类型特征时使用相同的模式:

  

23.15.3帮助器类[meta.help]
  [integrate_constant的定义]
  1类模板integer_constant,别名模板bool_constant及其关联的typedef名称true_type和false_type被用作基类,以定义各种类型特征的接口。

随后,该标准使用“具有……的基本特征”一词,如:

  

23.15.4一元类型特征[meta.unary]
  1本小节包含可用于在编译时查询类型属性的模板。
  2这些模板中的每个模板均应为UnaryTypeTrait(23.15.1),如果相应条件为true,则其基本特征为true_type,否则为false_type。

与先前的引用一起,我们可以得出结论,根据是否满足条件,有选择地继承true_typefalse_type是合法的。很难说出这个措词是否甚至可以强制继承,或者定义模板以使其仅像true_typefalse_type那样而没有显式继承自(但这是另一回事...)。

当然,由于我前面的“被用作”(与“可以用作”相反),我个人并不倾向于前一种解释。