在GNU编译器中,typedef的名称查找有缺陷

name lookup for typedef is buggy in GNU compiler?

本文关键字:查找 有缺陷 typedef GNU 编译器      更新时间:2023-10-16

以下代码

#include <iostream>
typedef double A; // a global typedef
template <class Z> struct B // a template class...
{
    A i{22.2}; // global typedef is in scope
    typedef int A; // now  a local typedef with the same name is introduced
    A b{24};  // now the local typedef is in scope
    Z c{36}; // a simple member of the template type
};
template <class Z> struct C : B<Z> // a template struct inheriting B
{
    A a;  // global typedef is in scope because we are in a template struct
    C(  ) : a(2.2){  }
};
int main(  )
{
    C<int> c;
    std::cout << "c's members: "
           << c.a << ' '
           << c.i << ' '
           << c.b << ' '
           << c.c << std::endl;
    std::cout << "their sizeof: "
           << sizeof(c.a) << ' ' 
           << sizeof(c.i) << ' '
           << sizeof(c.b) << ' '
           << sizeof(c.c) <<  std::endl;
}

不是由GNU-g++ 4.9.2编译的,而它是由clang 3.5.0编译的,它的行为正如我在嵌入的注释中试图解释的那样,正如它可以从生成的输出中看到的那样。这是GNU编译器中的一个错误吗?诊断显示typedef int A;线在struct B

错误:从"typedef double A"更改"A"的含义

注意,当层次结构不是由template组成时(当然,Z c{36};声明被删除),由clangC的范围内执行的查找(正确地,正如我所认为的)在B的范围内找到typedef,并认为成员a是CCD_ 12型;则发出初始化CCD_ 13常数CCD_。。。

来自c++标准草案(N4140)

§3.3.7【基本范围类别】

2) S类中使用的名称N在其上下文中以及在S的完整范围内重新评估时应指代相同的声明。违反此规则不需要进行诊断。

CCD_ 15最初指的是全局CCD_。但在声明B::A之后,当在B的已完成范围中重新评估时,它将引用B::A。这违反了上述规则。

要修复此问题,请使用完全限定名称:::A i{22.2}。即使在声明了B::A之后,::A也始终引用全局A,因此不违反规则。

这不是g++中的错误;这只是一个格式错误的程序。编译器不需要为您提供违反规则的诊断,但也不需要接受它。