Ich arbeite an einem großen Projekt, das einen Codeabschnitt enthält, der kompiliert - aber ich verstehe nicht wie. Ich habe es auf dieses einfache Beispiel heruntergerechnet:
%Vor% Die Klasse First
wird auf Traits
und Referenzen Traits::Three
aufgestempelt, was wiederum ein typedef
basierend auf Two
ist, was ein typedef
basierend auf First<Traits>
ist ... daher ist es kreisförmig. Aber dieser Code kompiliert sowohl gcc4.6 als auch VC10. Wenn ich jedoch die Reihenfolge der zwei Zeilen, die mit (A)
und (B)
markiert sind, umblättere, wird der Code nicht kompiliert und beschwert sich über typedef
in Second
.
Warum wird dieser Code kompiliert, und warum ist die Reihenfolge von typedef
und der Member-Variable wichtig?
Es gibt ein paar Dinge, die es Wert sind zu sagen.
Der Code wird abgebrochen, wenn Second
so geändert wird, dass
mit einer langen Kette "instanziert von ..." und endend mit einem "unvollständigen Typ" -Fehler aufgrund der erwarteten Kreisförmigkeit, aber nicht, wenn Sie stattdessen
hinzufügen %Vor% Dies sagt Ihnen, dass der Compiler es geschickt beobachtet. muss T
nicht vollständig einkapseln, nur um zu wissen, was T::type
ist. Um dies zu veranschaulichen, beachten Sie, dass Sie legal haben können
, da T keine aktuell definierten Objekte oder
enthält %Vor% da die typedef
in Second
auch keine Instanz von Objekten benötigt - aber nicht , sagen wir
Nur dann muss der Compiler tatsächlich ein First<Traits>
-Objekt innerhalb eines First<Traits>
-Objekts verschachteln.
Das Problem mit swapping (A) und (B) ist, dass der clevere Trick, den der Compiler oben gezogen hat, darin besteht, eine neue Kopie der Definition jeder spezialisierten Vorlage einzuführen, die eine Zeile bei a Zeit . Der Fehler tritt auf, wenn die Typdefinition in First
nicht erreicht wurde, wenn sie von Second
benötigt wird.
Sie benötigen keinen vollständigen Typ für typedef
.
Du hast eine Antwort angenommen, die viel besser war als die, die ich zur Verfügung gestellt habe - also entferne ich meine. Ich dachte jedoch, Sie könnten an einer weiteren Reduktion auf Ihr Beispiel interessiert sein. Ich habe zwei Zeilen als A und B markiert, um mit Ihrem ursprünglichen Code zu korrelieren. Wenn Sie sie umdrehen, wird die Kompilierung genauso wie in Ihrem Beispiel fehlschlagen.
%Vor%