【问题标题】:name lookup for typedef is buggy in GNU compiler?typedef 的名称查找在 GNU 编译器中有问题吗?
【发布时间】:2016-02-07 18:56:07
【问题描述】:

以下代码

#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 编译的,其行为与我试图在嵌入式 cmets 中解释的一样,并且可以从产生的输出中看出。这是 GNU 编译器中的错误吗? 诊断表明typedef int A; 范围内的行 struct B

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

请注意,当层次结构不是由template(当然Z c{36}; 声明被删除)时,clangC 范围内执行的查找(正确地,我想)会找到typedefB 的范围内,并认为成员 a 属于 输入int;然后它会发出关于初始化double 常量2.2 缩小的警告...

【问题讨论】:

标签: c++ c++11 typedef language-lawyer name-lookup


【解决方案1】:

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

§3.3.7 [basic.scope.class]

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

A i{22.2} 最初是指全局::A。但是在B::A被声明后,在B的完整范围内重新评估时,它会引用B::A。这违反了上面的规则。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 2021-01-31
    • 2014-08-12
    • 2016-10-08
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多