Warum sind redundante Klassennamenqualifizierer zulässig?

Ich bin auf folgenden Code gestoßen:

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);
}

Dies wurde unter Verwendung von VC11 Beta ohne Fehler oder Warnungen mit / W4 kompiliert und ausgeführt.

Die offensichtliche Absicht besteht darin, B :: init aufzurufen, um das A-Base-Unterobjekt von B neu zu initialisieren. Ich glaube, es wird tatsächlich als Variablendeklaration für eine neue Variable namens analysierti mit typA. Das Kompilieren mit clang erzeugt eine Diagnose:

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) {
                     ^

Es erscheint merkwürdig, dass der Typ mit der redundanten Klassenqualifikation bezeichnet werden kann.

Ebenfalls,A::A(i) scheint von VS11 und clang / gcc unterschiedlich analysiert zu werden. Wenn ich macheA::A(b) clang und gcc erzeugen eine Variableb vom TypA mit dem Standardkonstruktor. VS11 Fehler heraus auf diesem Sprichwortb ist eine unbekannte Kennung. VS11 scheint zu analysierenA::A(i) als die Schaffung eines temporärenA mit dem KonstruktorA::A(int) miti als Parameter. Wenn das redundante Qualifikationsmerkmal entfernt wird, analysiert VS die Quelle als Variablendeklaration, wie dies bei clang und gcc der Fall ist, und erzeugt einen ähnlichen Fehler beim Spiegeln der Variableni.

Dieser Unterschied beim Parsen erklärt, warum VS11 mehr als ein einziges zusätzliches Qualifikationsmerkmal verschluckt.A::A::A::A(i)und warum, da clang und gcc ein zusätzliches Qualifikationsmerkmal akzeptieren können, hat jede Zahl mehr als ein zusätzliches dasselbe Ergebnis wie ein zusätzliches.

Hier ist ein weiteres Beispiel mit den redundanten Qualifikationsmerkmalen in einem anderen Kontext. Alle Compiler scheinen dies als temporäre Konstruktion zu analysieren:

class Foo {};

void bar(Foo const &) {}

int main() {
    bar(Foo::Foo());
}
Warum sind redundante Qualifier überhaupt erlaubt?Es gibt einige Kontexte, in denen auf Konstruktoren verwiesen werden kann, z. B. die Syntax für die Vererbung von Konstruktoren (class D : B { using B::B; };) aber VS scheint es überall zuzulassen. Ist VS falsch und sind clang und gcc richtig, wie redundante Qualifikatoren analysiert werden?Ich weiß, dass VS in Bezug auf die Einhaltung von Standards noch ein gutes Stück hinterherhinkt, aber ich finde es ein bisschen überraschend, dass moderne, aktiv entwickelte Compiler so unterschiedlich sein können, dass sie in diesem Fall ein redundantes Qualifikationsmerkmal als Name eines Konstruktors auflösen (auch wenn Konstruktoren haben keine Namen) oder lösen redundante Qualifikationsmerkmale einfach in den Typ auf, was dazu führt, dass VS eine temporäre Variable erstellt, in der die anderen eine Variable deklarieren. Es kann noch schlimmer gemacht werden, woB b(A::A(i)); wird von clang und gcc als ärgerlichste Syntaxanalyse analysiert, aber VS sieht darin die Deklaration einer Variablenb vom TypB mit einem Initialisierer. Gibt es noch viele so gravierende Unterschiede?Es ist klar, dass redundante Qualifikationsmerkmale im portablen Code vermieden werden sollten. Gibt es eine gute Möglichkeit, die Verwendung dieses Konstrukts zu verhindern?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage