如果两个类都是模板,为什么我不能简单地使用基类中定义的类型?

时间:2015-03-01 09:55:06

标签: c++ templates inheritance

如果两个类都是模板,为什么我不能简单地使用基类中定义的类型?有关搜索模板成员的规则吗?这是我可以推断的最简单的例子:

struct iA {
    using type = int;
};
template <class T> struct tA {
    using type = T;
};

struct iB1 : iA {
    void f(type i) {}
};
struct iB2 : tA<int> {
    void f(type i) {}
};
template <class T> struct tB1 : iA {
    void f(type i) {}
};
template <class T> struct tB2 : tA<int> {
    void f(type i) {}
};
template <class T> struct tB3 : tA<T> {
    // void f(type i) {} // error: 'type' has not been declared
    void f(typename tA<T>::type i) {}
};

int main() {}

当然,我可以添加typename tA<T>::,但是有更优雅的解决方案吗?

1 个答案:

答案 0 :(得分:2)

问题是基类是依赖的,因此只有在我们查找依赖名称时才会检查其范围。 [temp.dep] / 3:

  

在类或类模板的定义中,如果是基类   取决于 template-parameter 不检查基类范围   在非限定名称查找期间或者在定义时   类模板或成员或在类的实例化期间   模板或成员。

此规则的原因是可能存在例如基类模板的特化。由于我们在定义时不知道特定的模板参数,因此我们无法检查基类的范围。

type不依赖,因此不会在依赖基础tA<T>中查找。但是,因为它不依赖,所以必须在定义时提供声明,[temp.res] / 10:

  

如果名称不依赖于模板参数(如中所定义)   14.6.2),该名称的声明(或一组声明)应在名称出现在模板中的范围内   定义;名称与声明(或声明)绑定   在那一点上找到并且此绑定不受声明的影响   在实例化时可见。


如果您需要在派生类中频繁使用typeusing声明可以提供帮助。

template <class T> struct tB3 : tA<T> {
    using typename tA<T>::type;
    void f(type i) {}
};

Demo