Ungültige Verwendung von unvollständigem Typ - warum kein Fehler in diesem Fall?

9

Ich bin verwirrt darüber, warum mein Code nicht den Fehler invalid use of incomplete type erzeugt, während all das Lesen, das ich über diesen Fehler gemacht habe, darauf hindeutet.
Die Frage ergab sich aus diesem Fehler angezeigt (wie erwartet) in dem Teil meines Codes mit einer ähnlichen Struktur, aber ich kann es nicht in einem kleinen Beispiel reproduzieren (siehe Haftungsausschluss am Ende der Frage) .

Zusammenfassung von dem, was ich versuche zu tun:

  • Ich habe eine Struktur ( Tree ), und ich möchte verschiedene Objekte vom Basistyp First zuweisen.
  • Konkrete Implementierungen von First haben unterschiedliche Rückgabewerte, daher werden zwei Ebenen der Indirektion verwendet:
  • First ist eine abstrakte Basisklasse und First * wird verwendet, um verschiedene konkrete Instanzen zu behandeln.
  • template <typename Type> class TypedFirst : public First ist ein abstrakter Typ, der die Funktion mit dem Rückgabetyp Type .
  • definiert
  • Schließlich sind ConcreteFirstX konkrete Spezialisierungen von TypedFirst<Type> .

In tree.tpp , warum erzeugt der Aufruf von new TF(this) nicht den Fehler invalid use of incomplete type ? (Der Spot ist im Code markiert) Ich denke, der Fehler sollte da sein, denn während TF eine Vorlage ist, wenn ich ConcreteFirstA verwende, ist tree.tpp davon nicht bewusst (es enthält nicht concretefirsta.h oder auch first.h , es nur forward deklariert First )

Der vollständige, kompilierbare und ausführbare Code für dieses Beispiel finden Sie hier auf pastebin . Hier werde ich aus Gründen der Kürze #define Wächter und ähnliche Dinge ausschließen. Der Code ist wie folgt:

%Vor% %Vor% %Vor%

Schließlich, der Code, der all das zusammenbringt und die (un) passenden Funktionsaufrufe macht:

%Vor%

HAFTUNGSAUSSCHLUSS Diese Frage wurde tatsächlich von einem größeren Problem ausgelöst, das ich im Stack Overflow-Format für zu groß und unzuverlässig hielt. Obwohl ich ursprünglich versucht habe, danach zu fragen, wurde die Frage als zu breit geschlossen und ich versuche nun, sie zu retten, indem ich nur einen Teil der Frage stelle.

Mein Problem ist, dass Ich bekomme den Fehler in einem Stück Code mit der gleichen Struktur wie dieser: aber, ich kann es nicht in einem kleinen Beispiel reproduzieren.

Daher frage ich warum der folgende Codecode nicht ist, der den Fehler invalid use of incomplete type erzeugt (wie ich es erwarten würde), und ich hoffe, dass mir das weiterhilft verstehe und löse mein tatsächliches Problem.

Bitte sagen Sie mir nicht, dass dies ein Fall von dem XY-Problem ist: Ich weiß, ich frage nicht nach Mein aktuelles Problem, weil ich (und die Community) es für dieses Format für zu groß hielt.

    
penelope 25.09.2014, 13:56
quelle

2 Antworten

2

main.cpp enthält tree.h , das (indirekt) die problematische Vorlage addFirstToTree() und concretefirsta.h enthält, die die Definition von ConcreteFirstA enthält.

Später in main.cpp , addFirstToTree() wird für den ConcreteFirstA -Typ instanziiert:

%Vor%

Dies ist der Punkt, an dem der Compiler genug über die Typen wissen muss, die als Template-Parameter verwendet werden, um den Compiler addFirstToTree() ausführen zu können. Und es weiß genug. ConcreteFirstA ist hier ein vollständiger Typ, da concretefirsta.h enthalten ist und die Klassendefinition enthält.

Früher in tree.tpp wo addFirstToTree() definiert ist, ConcreteFirstA ist noch nicht definiert, aber das spielt keine Rolle. Der Compiler sieht eine Vorlage und weiß nicht, für welche Template-Parameter diese Vorlage später instanziiert wird. Alle Funktionen / ..., die von einem Template-Parameter abhängen ("abhängige Namen"), können nicht aufgelöst werden, ohne zu wissen, für welche Parameter die Vorlage instanziiert wird, so dass die Namenssuche / ... bis später verschoben wird.

Sobald die Vorlage instanziiert ist und der Compiler alle abhängigen Namen auflöst und die Vorlage für die spezifischen Template-Parameter kompiliert. Da ConcreteFirstA zu diesem Zeitpunkt kein unvollständiger Typ ist, funktioniert dies ohne Fehler.

    
sth 26.09.2014 18:35
quelle
1

Weil Vorlagen erst kompiliert werden, wenn Sie sie mit konkreten Argumenten versehen haben.

Wenn der Compiler zur Zeile kommt:

%Vor%

es kompiliert die Funktion addFirstToTree zum ersten Mal mit dem Argument ConcreteFirstA , welches dort ein vollständig bekannter Typ ist.

Siehe cplusplus.com - Vorlagen

  

Sie werden bei Bedarf kompiliert, was bedeutet, dass der Code einer Template-Funktion erst kompiliert wird, wenn eine Instanziierung mit bestimmten Template-Argumenten erforderlich ist. In diesem Moment, wenn eine Instanziierung erforderlich ist, generiert der Compiler eine Funktion speziell für diese Argumente aus der Vorlage.

    
Ripple 26.09.2014 18:31
quelle

Tags und Links