如果两个 class 都是模板,为什么我不能简单地使用 base class 中定义的类型?
Why I can not simply use types defined in base class if both classes are templates?
如果两个 class 都是模板,为什么我不能简单地使用基 class 中定义的类型?是否有关于搜索模板成员的规则?这是我可以推断出的最简单的例子:
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>::
,但是有没有更优雅的方案呢?
问题是基础 class 是依赖的,因此只有在我们查找依赖名称时才会检查它的范围。 [temp.dep]/3:
In the definition of a class or class template, if a base class
depends on a template-parameter, the base class scope is not examined
during unqualified name lookup either at the point of definition of
the class template or member or during an instantiation of the class
template or member.
这条规则的原因是可能有例如基础 class 模板的特化。由于我们在定义时不知道具体的模板参数,因此我们无法检查基础 classes 作用域。
type
不是依赖项,因此不会在依赖库 tA<T>
中查找。但是,因为它不依赖,所以它的声明必须在定义时可用,[temp.res]/10:
If a name does not depend on a template-parameter (as defined in
14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template
definition; the name is bound to the declaration (or declarations)
found at that point and this binding is not affected by declarations
that are visible at the point of instantiation.
如果您需要在派生的 class 中频繁使用 type
,using
声明可以提供帮助。
template <class T> struct tB3 : tA<T> {
using typename tA<T>::type;
void f(type i) {}
};
Demo.
如果两个 class 都是模板,为什么我不能简单地使用基 class 中定义的类型?是否有关于搜索模板成员的规则?这是我可以推断出的最简单的例子:
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>::
,但是有没有更优雅的方案呢?
问题是基础 class 是依赖的,因此只有在我们查找依赖名称时才会检查它的范围。 [temp.dep]/3:
In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
这条规则的原因是可能有例如基础 class 模板的特化。由于我们在定义时不知道具体的模板参数,因此我们无法检查基础 classes 作用域。
type
不是依赖项,因此不会在依赖库 tA<T>
中查找。但是,因为它不依赖,所以它的声明必须在定义时可用,[temp.res]/10:
If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.
如果您需要在派生的 class 中频繁使用 type
,using
声明可以提供帮助。
template <class T> struct tB3 : tA<T> {
using typename tA<T>::type;
void f(type i) {}
};
Demo.