微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决为什么默认情况下隐藏模板基类的公共成员类型?

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
}

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

解决方法

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

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

U 本身不是依赖名称,因此编译器会在编译 B 的定义时尝试解析它。它此时无法查看 A<T> 的内部 - 它不知道 T 将是什么,或者是否会针对该 A 专门化 T可能会也可能不会声明名为 U 的成员。然后查找没有找到 U 的声明,因此出现错误。

U 中的

A<T>::U 是一个依赖名称,它的查找被推迟到 B<int> 被实例化。此时,编译器还会实例化 A<int> 并可以在其中查找 U 的声明。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。