C++ C++;使用相同名称为类型添加别名

C++ C++;使用相同名称为类型添加别名,c++,language-lawyer,C++,Language Lawyer,考虑以下代码: A类{}; B类{ 使用A=A; }; 对于Clang和ICC,这可以很好地编译,而GCC失败,并显示以下消息: error: declaration of ‘using A = class A’ changes meaning of ‘A’ [-fpermissive] 4 | using A = A; | ^ 问题:哪种编译器是正确的?为什么?Clang和ICC都是正确的 [basic.scope.pdecl] 。。。别名或别名模板

考虑以下代码:

A类{};
B类{
使用A=A;
};
对于Clang和ICC,这可以很好地编译,而GCC失败,并显示以下消息:

error: declaration of ‘using A = class A’ changes meaning of ‘A’ [-fpermissive]
    4 |   using A = A;
      |         ^

问题:哪种编译器是正确的?为什么?

Clang和ICC都是正确的

[basic.scope.pdecl]

。。。别名或别名模板的声明点紧跟在别名所引用的定义类型id之后

其中别名声明的语法为

[dcl.pre]

。。。
我们现在有了
A
引用了它的首次使用和完整类范围之间的不同声明。当然,命名的类型是相同的,但是通过不同的脱格。这足以使代码格式错误。GCC可能有一种启发式方法来保护代码不受此影响。它被你的良性例子绊倒了。

使用A=::A
应该可以解决这个问题。是的,但我不是在寻找解决方案,而是在寻找一个解释,哪个编译器可以在这里找到它;)这就是为什么它只是一个评论,而不是一个答案;)我已经把这个问题作为一个重复题结束了。有趣的是,因为有多篇关于重新定义类型的链接帖子,并且对代码是否正确有不同的解释,有时是在同一个问题上。@cigien-我想这取决于定义类型id中的“首次使用”是否足以违反p2。我不相信是这样。只有在没有歧义的情况下,A的含义才会改变。而且别名声明不像是在完整的类范围内“重新解析”的。这不是p2要避免的错误类别的一部分。如果GCC的解释确实是预期的。这对我来说似乎有点过分。当然,这不是一个应该编写的代码,但是对于[语言律师]问题,我们不必担心;)但是[basic/scope/class/#2]非常有趣。它通常指的是名称,而不仅仅是类型,我看到不同的答案对代码的有效性提出了不同的要求(编译器在很多情况下也不同意)。我一直想就这一要点做一个规范性的阐述,但还没有开始:(@cigien-我怀疑一个规范是可能的。它可能与各种声明点条款和类布局相互作用。贪图一切可能会因为过于宽泛而被关闭,即使在自我回答时也是如此。更不用说整个形式不良的NDR业务使得在意见不同时很难争论。你可以通过触及[temp.res]的问题看到它p8也是。 alias-declaration: using identifier attribute-specifier-seqopt = defining-type-id ;
class A {};

class B {
  A a;
  using A = A;
};