2015-09-06 14 views
10

Nach meiner Entdeckung der Inkonsistenz zwischen MSVC und GCC (wahrscheinlich auch klingeln) beim Kompilieren und Verknüpfen desselben Codes, bin ich neugierig geworden, sollte dieses Programm tatsächlich kompilieren und verlinken und es ist daher ein Bug in MSVC (der einen Linkerfehler meldet) oder sollte ich es anders schreiben. Das Programm besteht aus drei Dateien:Sollte das folgende Programm standardmäßig kompilieren?

Ch

template <typename T> 
struct A 
{ 
    void func() {}; 
}; 

template <> 
void A<int>::func(); 

A.cpp:

#include "C.h" 
int main() 
{ 
    A<int> x; 
    x.func(); 
} 

B.cpp:

#include "C.h" 
template <> 
void A<int>::func() 
{ 
} 

Der resultierende Linker-Fehler von MSVC ist:

A.OBJ

: Fehler LNK2019: nicht aufgelöstes externes Symbol "public: void __thiscall A :: func (void)"

Also im Grunde entscheidet es nicht Symbol aus Definition in B.cpp platziert zu erstellen. Die Sache, die mich stark als einen Fehler vermuten lässt, ist, dass das Verschieben der unspezialisierten Definition von func aus der Strukturdefinition und sogar das Überschreiben der Deklaration oberhalb der Spezialisierung das Programm linnking erfolgreich macht, aber ich möchte sicher sein.

Also meine Frage ist - sollte dieses Programm kompiliert und fehlerfrei von einem Compiler/Linker verknüpft werden?

+0

Sieht für mich wie ein Fehler aus. Verwenden Sie die neueste (2015) Version von MSVC? –

+0

@MatsPetersson Ja, 2015. – Predelnik

+0

Ihr Code kompiliert auch mit clang ++ gut.Es ist ein bisschen komisch tho ', da du im Wesentlichen zwei Definitionen für 'func' bereitstellst - ich bin nicht genug eines Sprachanwalts, um zu sagen, ob das richtig ist oder nicht (ich denke es ist) –

Antwort

1

Aus dem Standard:

© ISO/IEC N4527 14.6.4.1 Punkt Instanziierung [temp.point] 1 Für eine Funktion Vorlage Spezialisierung, eine Template-Spezialisierung Elementfunktion oder eine Spezialisierung für ein Member-Funktion oder statische Daten Mitglied einer Klasse Vorlage, wenn die Spezialisierung implizit instanziiert wird, weil es aus einem anderen Template-Spezialisierung verwiesen wird und der Kontext, aus dem sie verwiesen wird, hängt von einem Template-Parametern, den Punkt Instanziierung der Spezialisierung ist die Poi nt Instanziierung der umschließenden Spezialisierung. Andernfalls folgt der Punkt der Instanziierung für eine solche Spezialisierung unmittelbar der Namensraumbereich-Deklaration oder Definition, die sich auf die Spezialisierung bezieht.

In diesem Fall ich denke, dies ist bei C. H bedeutet, wo die „scope Erklärung“ auftritt. Wenn dies der Fall ist, sollte Ihr Code mit einer standardkonformen Werkzeugkette verknüpft werden. Ich könnte dies falsch interpretieren ...

-2

Unbenannte Namespaces haben interne Verknüpfung. Da sich die Template-Spezialisierung in einem unbenannten Namespace befindet, ist sie auch intern verlinkt.

Um das Problem zu lösen, legen Sie die Vorlage in einen benannten Namespace oder geben Sie die Spezialisierung als 'extern' an.

+0

"unbenannter Namensraum" bedeutet nicht, was Sie zu denken scheinen, dass es bedeutet. –