c++ - 当结构声明被变量隐藏时的名称解析

标签 c++ templates c++17 dependent-name name-hiding

让我们考虑以下演示程序。

#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();
}

可以看出,结构体A中的成员struct B的声明被具有以下特征的数据成员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编译器的bug。由于标准规则 typename T::B 应解析为变量而不是 struct B,因此这些规则列出如下:

A class name or enumeration name can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

上述规则表明,struct B 的名称被声明 int B = 20; 的名称隐藏了

When a qualified-id is intended to refer to a type that is not a member of the current instantiation ([temp.dep.type]) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. If the qualified-id in a typename-specifier does not denote a type or a class template, the program is ill-formed.

The usual qualified name lookup is used to find the qualified-id even in the presence of typename.

上面的规则表明关键字typename不会影响限定名称查找的结果,换句话说,关键字typename会影响不要求名称查找过程仅查找类型。

所以,在A范围内,int B = 20;struct B的声明都找到了,然后变量隐藏类名。因此,根据规则如果类型名称说明符中的qualified-id不表示类型或类模板,则程序格式错误,则程序应该格式错误。因此,GCC 8.3 是错误的。

另外,不仅是GCC 8.3,更高版本都是错误的。

关于c++ - 当结构声明被变量隐藏时的名称解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64335766/

相关文章:

templates - Visual Studio 2017 ASP NET Core 2 脚手架模板

c++ - C++ 模板中具有参数化类型的结构如何初始化?

c++ - 如何在现代 C++ 中使用分配器

c++ - 我可以使用特征指定变体的类型列表吗?

c++ - C++中套接字的HTTP请求

c++ - 如何从 vector 中提取n个样本?

c++ - 黑莓 10 : How to correspond incoming http replies to their previous http request counterparts?

c++ - 运算符重载使用operator +作为类模板

c++ - C++ 14或C++ 1z是否已经或将不再不确定以调用委托(delegate)类成员函数指针?

c++ - 查找两个字符串是否在O(n)中是字谜-使用XOR的解决方案