Ist dieser absurde Code, der sowohl in Clang als auch in GCC einen Fehler verursacht? [Duplikat]

8

Ich habe heute mit Templates herumgespielt, um zu sehen, ob ich den Compiler dazu bringen kann, den Typ einer äußeren Klasse von einer seiner inneren Klassen abzuleiten. Ich habe meine Lösung nicht gefunden (was ich für unmöglich halte), aber während ich versuchte, einen Fehler zu beheben, stieß ich auf ein sehr merkwürdiges Verhalten, das ich auf das folgende Snippet reduzierte.

%Vor%

Überraschenderweise kompiliert es ohne Warnungen und ohne Fehler sowohl mit Clang als auch mit GCC.
Die Versionen meiner Compiler sind gcc version 5.3.1 20160121 (Debian 5.3.1-7) und Debian clang version 3.6.2-3 (tags/RELEASE_362/final) (based on LLVM 3.6.2) und das Flag zum Kompilieren ist -std=c++11 -Wall -Wextra .

Ich habe beobachtet, dass es auch eine schöne auf Ideone mit der C ++ 14 Einstellung kompiliert.

Ich habe dann diesen einfachen Test verwendet, um die genauen Typen von InnerProblem und OuterProblem zu erhalten:

%Vor%

Und beide Compiler melden die gleichen Typen beim Kompilieren des Tests:

  

In der Funktion main :
  main.cpp: 20: undefinierter Verweis auf void Type<A::B>()
  main.cpp: 21: undefinierter Verweis auf void Type<void>()

Das heißt, der Typ von InnerProblem ist A::B und der Typ von OuterProblem ist void .

Ist das irgendwie vom Standard erlaubt oder ist es ein Fehler in beiden Compilern? Und da ich so verwirrt bin wie mein Compiler, was passiert eigentlich mit diesem Code?

BEARBEITEN : Als vereinfachten Nachfolger, weil ich nicht verstehe, warum zwei Compiler nicht das gleiche Ergebnis liefern können, kompiliert der folgende Code mit Clang, aber nicht mit GCC.

%Vor%

GCC gibt jetzt den folgenden Fehler aus:

  

main.cpp: 11: 26: error: 'A :: B :: B' benennt den Konstruktor, nicht den Typ      mit InnerProblem = EverythingIsFine :: Inner :: B :: B :: B; // Nicht ok

    
tux3 02.02.2016, 19:39
quelle

1 Antwort

6

Es ist gültig.

  

Der Klassenname wird auch in den Bereich der Klasse selbst eingefügt;   Dies wird als der Name der injected-Klasse bezeichnet. "(9/2).

So gibt B::B die Klasse B an, ebenso wie B::B::B und so weiter.

BEARBEITEN:

So gibt typename B::B die Klasse B an, ebenso wie typename B::B::B und so weiter.

    
Pete Becker 02.02.2016 19:45
quelle

Tags und Links