Wo sollte die Definition einer expliziten Spezialisierung einer Klassenvorlage in C ++ platziert werden?

8

Laut [temp.spec] / 5 :

  

Für eine gegebene Vorlage und einen gegebenen Satz von Template-Argumenten,

     
  • ...

  •   
  • Eine explizite Spezialisierung soll höchstens einmal in einem Programm definiert werden (nach [basic .def.odr] ) und

  •   
  • ...

  •   

Die Definition einer expliziten (vollständigen) Spezialisierung einer Klassenvorlage kann nicht in einer Kopfzeile platziert werden (andernfalls gibt es in jeder Übersetzungseinheit eine Definition, die diese Kopfzeile enthält, daher wird es mehr als eine Definition im gesamten Programm geben).

Als weiterer Beweis sind die in [basic.def.odr] aufgeführten Unternehmen / 12 (Blockquotting unten) enthalten keine vollständige Spezialisierung einer Klassenvorlage. Stattdessen ist "Vorlagenspezialisierung , für die einige Vorlagenparameter nicht angegeben sind " enthalten.

  

Es kann mehr als eine Definition eines Klassentyps, eines Aufzählungstyps, einer Inline-Funktion mit externer Verknüpfung geben ( [ dcl.inline] ), Inline-Variable mit externer Verknüpfung ( [dcl.inline] ) ), Klassenvorlage, nicht statische Funktionsvorlage, Konzept ( [temp.concept] ), statisch Datenelement einer Klassenvorlage, Elementfunktion einer Klassenvorlage oder Vorlagenspezialisierung, für die einige Vorlagenparameter nicht angegeben sind ( [temp.spec] , [temp.class.spec] ) in einem Programm vorausgesetzt, dass jede Definition in einer anderen Übersetzungseinheit erscheint und sofern die Definitionen die folgenden Anforderungen erfüllen.

Wenn ich jedoch die Definition in eine Quelldatei lege und ihre Deklaration in einer Kopfzeile belasse, z. B.

%Vor%

Dann tritt ein Fehler auf ( getestet von gcc ), weil S<int> ein unvollständiger Typ ist.

Abschließend, wo sollte ich die Definition einer expliziten Spezialisierung einer Klassenvorlage platzieren?

    
xskxzr 29.11.2017, 02:56
quelle

3 Antworten

1

Ich werde versuchen, hier zusammenzufassen, was ich durch die Diskussion in meiner anderen Antwort gelernt habe , in der Hoffnungen, eine gute Antwort auf diese Frage zu hinterlassen, anstatt die Antwort in den Kommentaren begraben zu lassen.

Der Standard sagt

  

Eine explizite Spezialisierung soll höchstens einmal in einem Programm definiert werden (nach ODR)

ODR ist die eine Definitionsregel. Sie können jede Klasse nur einmal innerhalb eines Programms definieren, mit einer Ausnahme, die es erlaubt, eine Klassendefinition in jeder Übersetzungseinheit verfügbar zu machen: Sie können eine Klasse in verschiedenen Übersetzungseinheiten definieren, solange diese verschiedenen Definitionen Zeichen für Zeichen identisch sind. Das Zitat des OP ist Teil der ODR-Beschreibung. Folgen Sie dem Link des OP , um das zu sehen vollständige Beschreibung.

IMO besagt also, dass eine explizite Spezialisierung nur einmal definiert werden kann, aber gemäß der ODR und damit mit den gleichen Ausnahmen: Sie können sie in einer Header-Datei definieren, so dass sie in mehreren Übersetzungseinheiten verfügbar ist.

Beachten Sie, dass es nicht möglich ist, eine Klasse ohne ihre vollständige Definition zu instanziieren (der Compiler muss mindestens wissen, wie viele Bytes er dafür reservieren muss). Dasselbe gilt für eine Vorlagenklasse oder eine Spezialisierung einer solchen Klasse. Daher muss möglich sein, damit die Definition in jeder Übersetzungseinheit vorhanden ist, in der sie verwendet wird.

    
Cris Luengo 03.12.2017, 21:50
quelle
0

Dies ist eine Definition (die Spezialisierung wird instanziiert), keine Deklaration, sie sollte wahrscheinlich in eine bestimmte Quelldatei (* .cpp) gehen:

%Vor%

Hinweis: Es tut nicht weh, dies in jeder Übersetzungseinheit zu haben ... außer der Zeit, die der Compiler für die Instanziierung benötigt, und dem Bloat für die Objektdateien (* .o oder * .obj) .

Dies ist eine Deklaration (die Spezialisierung wird nicht instanziiert), und es ist in Ordnung, eine Header-Datei (* .h) einzufügen:

%Vor%

Die Deklaration erfordert C ++ 11 oder höher.

    
Eljay 29.11.2017 13:22
quelle
-1

Sie können keine Klasse instanziieren, die in der Übersetzungseinheit nicht vollständig definiert ist. Klassenvorlagenspezialisierungen gehören in die Header-Datei. Sie können eine Funktion oder Methodenspezialisierung in eine separate Übersetzungseinheit schreiben:

%Vor%

BEARBEITEN:

Wenn der Standard sagt

  

Eine explizite Spezialisierung soll maximal einmal in einem Programm definiert werden (nach [basic.def.odr])

Es heißt, dass Sie laut ODR nicht mehr als eine Definition haben können. Das Gleiche gilt für alles andere: Sie können nicht zwei verschiedene Klassen mit demselben Namen deklarieren, so dass Sie nicht zwei verschiedene Spezialisierungen mit denselben Template-Parametern deklarieren können. Das Einfügen einer Klassendefinition in eine Header-Datei verletzt ODR nicht. Weder spezialisiert sich eine Klassenvorlage.

    
Cris Luengo 03.12.2017 14:57
quelle