首页 > 解决方案 > 为什么默认隐藏模板基类的公共成员类型?

问题描述

template<typename T>
struct A
{
    using U = T;
};

template<typename T>
struct B : A<T>
{
    B(typename A<T>::U) {} // okay
    B(U) {} // error: unknown type name 'U'
};

int main()
{
    return typename B<int>::U{}; // okay
}

为什么默认隐藏模板基类的公共成员类型?

标签: c++c++11templatesinheritancename-hiding

解决方案


进一步研究的搜索词是“两阶段名称查找”。

简而言之,编译器尝试在定义模板时解析模板使用的尽可能多的名称。一些名称——所谓的“依赖名称”——此时无法解析,必须推迟到模板实际实例化并且其参数变得已知时。粗略地说,这些是从语法中出现的名称,取决于模板参数。

U本身不是依赖名称,因此编译器会在编译B. 它此时无法查看内部A<T>- 它不知道T将要发生什么,也不知道是否会有一个可能会或可能不会声明名为 的成员的A特化。然后查找找不到 的声明,因此出现错误。TUU

UinA<T>::U是一个从属名称,它的查找被推迟到B<int>被实例化。此时,编译器也会实例化A<int>并在其中查找U.

这也是你需要写typename的原因typename A<T>::U。编译器无法查找依赖名称的声明U,但它至少需要知道它是类型还是非类型,因为低级词法分析依赖于此(经典示例X*Y;可能是解析为指针的声明,或使用乘法的表达式,具体取决于是否X是类型)。typename所以规则是,除非前面有关键字,否则假定依赖名称是指非类型。


推荐阅读