c++ - 结构声明被变量隐藏时的名称解析
问题描述
让我们考虑以下演示程序。
#include <iostream>
struct A
{
struct B
{
int b = 10;
};
int B = 20;
};
template <class T>
struct C
{
void f() const
{
typename /*struct*/ T::B b;
int x = b.b;
std::cout << "x == " << x << '\n';
}
};
int main()
{
C<A>().f();
}
正如所见,struct B
结构中成员的声明被类型A
为 的数据成员的声明所隐藏。B
int
所以在模板结构声明的函数定义中
typename /*struct*/ T::B b;
T::B
不应该找到依赖的名称。
但是编译器gcc 8.3
成功编译程序并且程序输出
x == 10
另一方面,编译器Visual C++ 2019不会编译程序并发出语法错误。
那么它是编译器gcc 8.3的错误吗?
第二个问题是,如果允许这种带有详细类型说明符的构造(带有未注释的关键字结构)是很自然的。
typename struct T::B b;
但是,两个编译器都认为该构造不正确。
确实不正确吗?
解决方案
应该是编译器gcc 8.3的bug。因为标准规则typename T::B
应该被解析为变量而不是struct B
,所以下面列出了这些规则:
类名或枚举名可以被同一作用域中声明的变量、数据成员、函数或枚举器的名称隐藏。如果一个类或枚举名称和一个变量、数据成员、函数或枚举器在同一范围内(以任何顺序)以相同名称声明,则无论变量、数据成员、函数或枚举器名称可见。
上面的规则说的名字struct B
被声明的名字隐藏了int B = 20;
当qualified-id 旨在引用不是当前实例化成员的类型([temp.dep.type])并且其nested-name-specifier 引用依赖类型时,应以关键字为前缀typename,形成一个 typename-specifier。如果 typename-specifier 中的qualified-id 不表示类型或类模板,则程序格式错误。
即使在 typename 存在的情况下,通常的限定名称查找也用于查找限定 ID。
上面的规则说关键字typename
不影响 的结果qualified name lookup
,换句话说,关键字typename
不要求名称查找过程只查找类型。
所以,在 的范围内,和A
的声明都找到了,然后变量就隐藏了。因此,根据规则如果 typename-specifier 中的qualified-id 不表示类型或类模板,则程序是 ill-formed,该程序应该是 ill-formed 。因此,GCC 8.3是错误的。int B = 20;
struct B
class name
此外,不仅GCC 8.3
是更高的版本都是错误的。
推荐阅读
- ibm-midrange - IBM i SQL 中的主机变量可以有空格吗?
- java - 如何在android中过滤自定义ListView
- protractor - 使用 chrome 访客模式启动量角器
- c++ - 使蒙版外全部透明
- python - 如何矢量化循环遍历 3D 点数组的 Python 函数?
- ios - 不在摄像机视野内时停止 SKVideoNode 播放
- laravel - barryvdh/laravel-cors 配置在 Laravel 5.6 中不起作用;忽略'allowedMethods'
- html - 我如何在 Bootstrap 中强制图像粘贴到它下面的 div 直到 768px
- javascript - Ionic 3 中的 CORS 地狱
- ruby-on-rails - Rails 应用程序中的语言没有改变