注入的类名编译器差异

Tar*_*ama 22 c++ gcc clang language-lawyer c++14

考虑以下代码:

struct foo{};

int main() {
    foo::foo a;
}
Run Code Online (Sandbox Code Playgroud)

我希望这个格式正确,foo通过[class]/2中的规则声明一个类型的变量(N4140,强调我的):

一个类名被插入在其中后立即宣布的范围类的名字能够被看见. 类名也被插入到类本身的范围 ; 这被称为注入类名.出于访问检查的目的,inject-class-name被视为公共成员名称.

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;
Run Code Online (Sandbox Code Playgroud)

无论注入的类名称的嵌套有多深,例如,上述情况都适用foo::foo::foo::foo.

是否存在强制该构造在该上下文中被解释为构造函数的规则,或者这是一个gcc错误?或者我是否错误地解释标准报价?

Tar*_*ama 13

clang在这种情况下似乎是错误的.我正在寻找的相关例外是[class.qual]/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
Run Code Online (Sandbox Code Playgroud)

但是,clang实际上在这种情况下会发出正确的诊断:

error: qualified reference to 'A' is a constructor name rather than a type wherever a constructor can be declared
Run Code Online (Sandbox Code Playgroud)

也许clang将这条线解释In a lookup in which function names are not ignoredIn a lookup in which a constructor declaration is valid,但这似乎不是一个正确的解释.

有一个存在的bug在此clang的Bugzilla.

  • 我的报告较旧,而且是拒绝有效的:https://llvm.org/bugs/show_bug.cgi?id = 8263:p (2认同)

ret*_*idi 7

相关的,但不是一个答案:海湾合作委员会讨论的人正是几年和揣摩,它不应该被接受.他们在GCC 4.5及更新版本中明确指出这是一个错误- 在4.4.7中它被接受了.

顺便说一句:你可能想要使用Clang -Weverything而不是-Wall -pedantic调查这些东西.