注入的类名编译器不一致

Injected class name compiler discrepancy

本文关键字:编译器 不一致 注入      更新时间:2023-10-16

考虑以下代码:

struct foo{};
int main() {
    foo::foo a;
}

我希望这是格式良好的,根据[class]/2 (N4140,强调我的)中的规则声明类型为foo的变量:

类名出现后,立即将类名插入声明它的作用域。类名也被插入到类本身的作用域;这就是所谓的注入类名。出于访问检查的目的,注入的类名被视为公共成员名。

clang 3.6.0同意我的观点,用-Wall -pedantic编译上面的代码,没有任何适用的警告。

gcc 5.2.0不同意,提供以下错误消息:

main.cpp: In function 'int main()':
main.cpp:5:5: error: 'foo::foo' names the constructor, not the type
   foo::foo a;

无论注入的类名嵌套有多深,上面的规则都成立,例如foo::foo::foo::foo

是否有规则强制构造在该上下文中被解释为构造函数,或者这是gcc的错误?还是我对标准引用的解释不正确?

在这种情况下,clang似乎是错误的。我正在寻找的相关异常在[class. quality]/2:

中。

2函数名不被忽略且嵌套名称说明符指定类C的查找:

  • (2.1)如果在嵌套名称说明符后指定的名称在C中查找时是C

  • 的注入类名,则
  • […]

这个名字被认为是c类构造函数的名字。

标准有一个近似的(非规范的,明显的)例子:

struct A { A(); };
struct B: public A { B(); };
A::A() { }
B::B() { }
B::A ba;// object of type A
A::A a;// error, A::A is not a type name
struct A::A a2;// object of type A

然而,clang实际上给出了正确的诊断:

error: qualified reference to 'A' is a constructor name rather than a type wherever a constructor can be declared

也许clangIn a lookup in which function names are not ignored行解释为In a lookup in which a constructor declaration is valid,但这似乎不是一个正确的解释。

clang bugzilla中存在此错误

相关,但不是答案:GCC人员多年来一直在讨论这个问题,并且认为它不应该被接受。在GCC 4.5和更新的版本中,他们明确地把这个错误变成了一个错误——在4.4.7中它被接受了。

BTW:你可能想用Clang的-Weverything而不是-Wall -pedantic来研究这些东西。

我认为这是语言缺陷#147的主题其中包含以下示例

class B { };
class A: public B {
    A::B ab;       // B is the inherited injected B
    A::A aa;       // Error: A::A is the constructor
};

至少gcc似乎相信这一点。: -)