[英]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
}
Why can't the class inherit the member types of its parents?为什么 class 不能继承其父级的成员类型?
The member U
is inherited like any other member would be, irrespective of which classes are templated, but it is not found by unqualified name lookup according to C++17 [temp.dep]/3:成员U
像任何其他成员一样被继承,无论模板化了哪些类,但根据 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. 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成员。
Here, A<T>
is a dependent base class since it depends on the template parameter T
of the class template D
.这里, A<T>
是一个依赖基础 class 因为它依赖于 class 模板D
的模板参数T
。
To force the compiler to look up U
in the base class, you have to use qualified name lookup.要强制编译器在基础 class 中查找U
,您必须使用限定名称查找。 You can do it like this:你可以这样做:
void f(typename A<T>::U);
Another way of expressing it, if the template arguments to the base class are complicated, is:另一种表达方式是,如果模板 arguments 到基础 class 很复杂,则为:
void f(typename D::A::U);
If you are going to be writing this out multiple times then you could also redeclare the type in D
for convenience:如果你要多次写出来,那么你也可以为了方便重新声明D
中的类型:
using U = typename A<T>::U;
void f(U);
Note: in the above contexts, typename
will become optional in C++20.注意:在上述上下文中, typename
在 C++20 中将变为可选。
Because as a non-dependent name, U
won't be looked up in dependent base class A<T>
, which depends on template parameter T
.因为作为非依赖名称, U
不会在依赖基础 class A<T>
中查找,这取决于模板参数T
。 On the other hand, for both B
and C
their base class are non-dependent base class.另一方面,对于B
和C
,它们的基础 class 是非依赖基础 class。
You can change to dependent name, eg A<T>::U
, which depends on template parameter T
too.您可以更改为依赖名称,例如A<T>::U
,这也取决于模板参数T
。 Dependent names may be looked up only at the time of instantiation, at that time the exact specialization (including base class) will be known.依赖名称只能在实例化时查找,那时确切的专业化(包括基类)将是已知的。
template<typename T>
struct D : A<T>
{
void f(typename A<T>::U)
{}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.