如果两个类都是模板,为什么我不能简单地使用基类中定义的类型?有关搜索模板成员的规则吗?这是我可以推断的最简单的例子:
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>::
,但是有更优雅的解决方案吗?
答案 0 :(得分:2)
问题是基类是依赖的,因此只有在我们查找依赖名称时才会检查其范围。 [temp.dep] / 3:
在类或类模板的定义中,如果是基类 取决于 template-parameter ,不检查基类范围 在非限定名称查找期间或者在定义时 类模板或成员或在类的实例化期间 模板或成员。
此规则的原因是可能存在例如基类模板的特化。由于我们在定义时不知道特定的模板参数,因此我们无法检查基类的范围。
type
不依赖,因此不会在依赖基础tA<T>
中查找。但是,因为它不依赖,所以必须在定义时提供声明,[temp.res] / 10:
如果名称不依赖于模板参数(如中所定义) 14.6.2),该名称的声明(或一组声明)应在名称出现在模板中的范围内 定义强>;名称与声明(或声明)绑定 在那一点上找到并且此绑定不受声明的影响 在实例化时可见。
如果您需要在派生类中频繁使用type
,using
声明可以提供帮助。
template <class T> struct tB3 : tA<T> {
using typename tA<T>::type;
void f(type i) {}
};