为什么 class 不能继承其父类的成员类型?
Why can't the class inherit the member types of its parents?
template<typename T>
struct A
{
using U = int;
};
struct B : A<int>
{
void f(U) // ok
{}
};
template<typename T>
struct C : A<int>
{
void f(U) // ok
{}
};
template<typename T>
struct D : A<T>
{
void f(U) // fatal error: unknown type name 'U'
{}
};
int main()
{
B b; // ok
C<int> c; // ok
D<int> d; // error
}
为什么class不能继承其父类的成员类型?
因为作为非依赖名称,U
不会在依赖库 class A<T>
中查找,这取决于模板参数 T
。另一方面,对于 B
和 C
它们的基础 class 是非依赖基础 class.
您可以更改为相关名称,例如A<T>::U
,这也取决于模板参数 T
。从属名称可能仅在实例化时查找,届时将知道确切的特化(包括基础 class)。
template<typename T>
struct D : A<T>
{
void f(typename A<T>::U)
{}
};
成员 U
像任何其他成员一样被继承,而不管哪个 classes 是模板化的,但是根据 C++17 [temp.dep]/3:
In the definition of a class or class template, the scope of a dependent base class (17.6.2.1) 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.
这里,A<T>
是一个依赖基class,因为它依赖于class模板D
的模板参数T
。
要强制编译器在基 class 中查找 U
,您必须使用限定名称查找。你可以这样做:
void f(typename A<T>::U);
如果基数 class 的模板参数很复杂,另一种表达方式是:
void f(typename D::A::U);
如果您打算多次写出这个,那么为了方便起见,您也可以在 D
中重新声明类型:
using U = typename A<T>::U;
void f(U);
注意:在上述情况下,typename
在 C++20 中将变为可选。
template<typename T>
struct A
{
using U = int;
};
struct B : A<int>
{
void f(U) // ok
{}
};
template<typename T>
struct C : A<int>
{
void f(U) // ok
{}
};
template<typename T>
struct D : A<T>
{
void f(U) // fatal error: unknown type name 'U'
{}
};
int main()
{
B b; // ok
C<int> c; // ok
D<int> d; // error
}
为什么class不能继承其父类的成员类型?
因为作为非依赖名称,U
不会在依赖库 class A<T>
中查找,这取决于模板参数 T
。另一方面,对于 B
和 C
它们的基础 class 是非依赖基础 class.
您可以更改为相关名称,例如A<T>::U
,这也取决于模板参数 T
。从属名称可能仅在实例化时查找,届时将知道确切的特化(包括基础 class)。
template<typename T>
struct D : A<T>
{
void f(typename A<T>::U)
{}
};
成员 U
像任何其他成员一样被继承,而不管哪个 classes 是模板化的,但是根据 C++17 [temp.dep]/3:
In the definition of a class or class template, the scope of a dependent base class (17.6.2.1) 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.
这里,A<T>
是一个依赖基class,因为它依赖于class模板D
的模板参数T
。
要强制编译器在基 class 中查找 U
,您必须使用限定名称查找。你可以这样做:
void f(typename A<T>::U);
如果基数 class 的模板参数很复杂,另一种表达方式是:
void f(typename D::A::U);
如果您打算多次写出这个,那么为了方便起见,您也可以在 D
中重新声明类型:
using U = typename A<T>::U;
void f(U);
注意:在上述情况下,typename
在 C++20 中将变为可选。