为什么允许冗余类名限定符? [英] Why are redundant class name qualifiers allowed?

查看:182
本文介绍了为什么允许冗余类名限定符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了这样的代码:

struct A {
    A() {}
    A(int) {}
};

struct B : A {
    void init(int i);
};

void B::init(int i) {
    A::A(i); // what is this?
}

int main() {
    B b;
    b.init(2);
}

这是使用VC11测试版编译和运行的,不带/ W4的错误或警告。

This compiled and ran using VC11 beta with no errors or warnings with /W4.

显而易见的意图是调用B :: init重新初始化B的A基本子对象。我相信它实际上解析为一个变量声明为一个名为 i 的类型为 A 的变量。使用clang编译会生成诊断信息:

The apparent intent is for calling B::init to reinitialize the B's A base subobject. I believe it actually parses as a variable declaration for a new variable named i with type A. Compiling with clang produces diagnostics:

ConsoleApplication1.cpp:11:14: warning: declaration shadows a local variable
        A::A(i);
             ^
ConsoleApplication1.cpp:10:22: note: previous declaration is here
    void B::init(int i) {
                     ^
ConsoleApplication1.cpp:11:14: error: redefinition of 'i' with a different type
        A::A(i);
             ^
ConsoleApplication1.cpp:10:22: note: previous definition is here
    void B::init(int i) {
                     ^

似乎很好奇,类型可以通过冗余类限定来引用。

It seems curious that the type can be referred to with the redundant class qualification.

另外, A :: A(i)似乎被VS11和clang / gcc解析不同。如果我做 A :: A(b) clang和gcc创建 b > A 使用默认构造函数。 VS11错误的说: b 是一个未知的标识符。 VS11似乎解析 A :: A(i)作为使用构造函数<$ c创建临时 A $ c> A :: A(int)以 i 作为参数。当消除冗余限定符时,VS将源解析为变量声明,如clang和gcc do,并且产生关于变量 i 的类似错误。

Also, A::A(i) appears to be parsed differently by VS11 and clang/gcc. If I do A::A(b) clang and gcc create a variable b of type A using the default constructor. VS11 errors out on that saying b is an unknown identifier. VS11 appears to parse A::A(i) as the creation of a temporary A using the constructor A::A(int) with i as the parameter. When the redundant qualifier is eliminated VS parses the source as a variable declaration like clang and gcc do, and produces a similar error about shadowing the variable i.

这种解析的区别解释了为什么VS11会阻塞一个额外的限定符; A :: A :: A :: A(i),以及为什么,考虑到clang和gcc可以接受一个额外的限定符,任何数字多于一个额外具有相同

This difference in parsing explains why VS11 will choke on more than a single extra qualifier; A::A::A::A(i), and why, given that clang and gcc can accept one extra qualifier, any number more than one extra has the same result as one extra.

这是另一个在不同上下文中使用冗余限定符的例子。所有编译器似乎都解析为临时结构:

Here's another example with the redundant qualifiers in a different context. All compiler seem to parse this as a temporary construction:

class Foo {};

void bar(Foo const &) {}

int main() {
    bar(Foo::Foo());
}




  1. 为什么允许冗余限定符? / li>
  2. 有一些上下文可以引用构造函数,例如继承构造函数的语法( class D:B {using B :: B;}; code>)但VS似乎允许它在任何地方。是VS错误,是clang和gcc对如何解析多余的限定符吗?

  3. 我知道VS在标准合规方面仍然落后,但我确实发现有点令人惊讶现代的,积极开发的编译器可能是如此分歧,在这种情况下,解析冗余限定符作为构造函数的名称(尽管构造函数没有名称),而只是简单地将冗余限定符解析为类型,导致VS构造临时其他人声明一个变量。在 B b(A :: A(i)); 被clang和gcc解析为最烦琐的解析,但是VS认为它是声明带有初始化程序的 B 类型的变量 b 这是否还有很多差异吗?

  4. 很明显,在可移植代码中应该避免使用冗余限定符。是否有很好的方法可以防止此结构被使用?

  1. Why are redundant qualifiers allowed at all?
  2. There are some contexts where constructors can be referred to, such as the syntax for inheriting constructors (class D : B { using B::B; };) but VS seems to be allowing it anywhere. Is VS wrong and are clang and gcc right in how redundant qualifiers are parsed?
  3. I know VS is still a fair bit behind in terms of standards compliance, but I do find it a bit surprising that modern, actively developed compilers could be so divergent, in this case resolving a redundant qualifier as the name of a constructor (even though constructors don't have names) vs. resolving redundant qualifiers simply to the type, resulting in VS constructing a temporary where the others declare a variable. It can be made even worse where B b(A::A(i)); is parsed by clang and gcc as the most vexing parse, but VS sees it as declaring a variable b of type B with an initializer. Are there still many differences this severe?
  4. Clearly, redundant qualifiers should be avoided in portable code. Is there a good way to prevent this construct from being used?


推荐答案

可能归因于类名注入,正如ephemient的回答中所指出的,对于这个特定的例子,它已经被C ++语言取消了。

While the phenomenon can probably be attributed to class name injection, as noted in ephemient's answer, for this specific example it has been outlawed by C++ language quite a while ago.

http:/ /www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#147

组合 A :: A 是引用类构造函数所必需的,而不是注入的类名。 A :: A(i)应该由兼容的编译器解释为涉及构造函数名称的非法(因此无意义)表达式。例如,Comeau编译器将拒绝编译您的代码。

The combination A::A is required to refer to class constructor, not to the class injected name. The A::A(i) is supposed to be interpreted by a compliant compiler as an illegal (and therefore meaningless) expression involving constructor name. Comeau compiler, for one example, will refuse to compile your code for that reason.

显然,VC11继续处理 A :: A 作为注入类名的引用。有趣的是,我在VS2005中没有观察到这个问题。

Apparently VC11 continues to treat A::A as a reference to the injected class name. Interestingly enough, I don't observe this problem in VS2005.

回到 A :: A 被解释为引用注入的名称,可以将 A 对象声明为

Back in the day when A::A was interpreted as referring to the injected name, one could declare an A object as

A::A::A::A::A::A a;

等等,任意数字 A s。但不再。令人惊讶的是,ideone使用的GCC版本(4.3.4?)仍然遇到此问题

and so on, with arbitrary number of As. But not anymore. Surprisingly, version of GCC (4.3.4?) used by ideone still suffers from this issue

http://ideone.com/OkR0F

您可以尝试使用您的VC11版本,看看是否允许。

You can try this with your version of VC11 and see if it allows that.

这篇关于为什么允许冗余类名限定符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆