如何解决结构声明被变量隐藏时的名称解析
让我们考虑以下演示程序。
#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 的错误吗?
第二个问题是,如果允许这样的结构(带有未注释的关键字struct)和详细的类型说明符,那将是很自然的。
typename struct T::B b;
但是,两个编译器都认为构造不正确。
这确实不正确吗?
解决方法
这应该是编译器gcc 8.3的错误。因为将typename T::B
解析为变量而不是struct B
的标准规则,所以以下列出了这些规则:
类名或枚举名称可以被在同一范围内声明的变量,数据成员,函数或枚举器的名称隐藏。如果在相同的作用域(以任何顺序)中以相同的名称声明了类或枚举名称以及变量,数据成员,函数或枚举器,则无论变量,数据成员,函数或枚举器名称可见。
上面的规则说struct B
的名称被声明int B = 20;
的名称隐藏了
当限定ID引用的类型不是当前实例的成员([temp.dep.type]),并且其嵌套名称说明符引用的是依赖类型时,应在其前面添加前缀由关键字typename组成一个typename-specifier。如果typename-specifier中的qualified-id不表示类型或类模板,则程序格式错误。
通常的合格名称查找用于查找合格ID,即使存在typename也是如此。
以上规则说关键字typename
不会影响qualified name lookup
的结果,换句话说,关键字typename
并不要求名称查找过程只能找到类型。
因此,在A
的范围内,都找到了int B = 20;
和struct B
的声明,然后变量隐藏了class name
。因此,根据规则,如果typename-specifier中的qualified-id不表示类型或类模板,则程序格式错误,则程序应格式错误。因此, GCC 8.3 是错误的。
此外,不仅GCC 8.3
而且更高版本都是错误的。
从我的角度来看:在 f()函数中,您需要声明 struct 以避免出现此问题
template <class T> struct C {
void f() const {
// just normal struct
struct T::B structB;
int x = structB.b;
std::cout << "x == " << x << std::endl;
}
};
并通常在 main 中调用 f():
C<A> j;
// call
j.f();
我希望所有这些都值得:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。