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:
Tree
), und ich möchte verschiedene Objekte vom Basistyp First
zuweisen. 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
. 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:
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.
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:
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.
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.
Tags und Links c++ templates incomplete-type