Ich glaube, diese beschränken sich im Wesentlichen auf [temp.inst] / 2 (Hervorhebung von mir):
Die implizite Instanziierung einer Klassenvorlagenspezialisierung bewirkt die implizite Instanziierung der Deklarationen, jedoch nicht der Definitionen , Standardargumente oder Noexcept-Spezifizierer der Klassenelementfunktionen, Elementklassen, Elementaufzählungen mit Gültigkeitsbereich, statischen Datenelemente , Elementvorlagen und Freunde; […]
und [temp.inst] / 9
Eine Implementierung darf ein statisches Datenelement einer Klassenvorlage […] nicht implizit instanziieren […], es sei denn, eine solche Instanziierung ist erforderlich.
Der Wortlaut des Standards zur impliziten Instanziierung von Vorlagen lässt viele Details für die Interpretation offen. Im Allgemeinen scheint es mir, dass Sie sich einfach nicht darauf verlassen können, dass Teile einer Vorlage nicht instanziiert werden, es sei denn, die Spezifikation sagt dies ausdrücklich aus. Somit:
Snippet # 1
F. Warum wird dieser Code kompiliert? Instanziieren wir nicht A, wenn wir von B erben? Es gibt kein VD in B, sollte der Compiler hier also keinen Fehler auslösen?
Sie instanziieren A<B>
. Durch das Instanziieren werden jedoch A<B>
nur die Deklarationen instanziiert, nicht die Definitionen der statischen Datenelemente. VB
wird niemals so verwendet, dass eine Definition erforderlich wäre. Der Compiler sollte diesen Code akzeptieren.
Snippet # 2
F. Warum wird es mit gcc9 kompiliert / warum wird es nicht mit clang9 kompiliert?
Wie von Jarod42 hervorgehoben, ist die Erklärung von AB
enthält einen Platzhaltertyp. Es scheint mir, dass der Wortlaut des Standards nicht wirklich klar ist, was hier passieren soll. Löst die Instanziierung der Deklaration eines statischen Datenelements, das einen Platzhaltertyp enthält, einen Platzhaltertypabzug aus und stellt somit eine Verwendung dar, die die Definition des statischen Datenelements erfordert? Ich kann in der Norm keinen Wortlaut finden, der eindeutig Ja oder Nein dazu sagt. Daher würde ich sagen, dass beide Interpretationen hier gleichermaßen gültig sind und somit sowohl GCC als auch Clang richtig sind…
Snippet # 3
F. Wenn Struktur B hier unvollständig ist, warum ist sie dann in Snippet 2 nicht unvollständig?
Ein Klassentyp ist erst an dem Punkt vollständig, an dem Sie das Schließen }
des Klassenspezifizierers [class.mem] / 6 erreichen . Somit B
ist während der impliziten Instanziierung A<B>
in all Ihren Snippets unvollständig . Es ist nur so, dass dies für Snippet # 1 irrelevant war. In Snippet # 2 hat clang No member named AD in B
als Ergebnis einen Fehler ausgegeben . Ähnlich wie im Fall von Snippet Nr. 2 kann ich keine Formulierung finden, wann genau die Alias-Deklarationen der Mitglieder instanziiert würden. Anders als bei der Definition statischer Datenelemente gibt es jedoch keinen Wortlaut, der die Instanziierung von Elementaliasdeklarationen während der impliziten Instanziierung einer Klassenvorlage explizit verhindert. Daher würde ich sagen, dass das Verhalten von GCC und Clang in diesem Fall eine gültige Interpretation des Standards ist…
struct B
Instanziiert nichtA
mitB
?