VC++2010: Comdat-Nerv und mehrere Definitionen (Template Funktionen)
-
Ich hab ein Problem im Zusammenhang mit Templatefunktionen.
Ich hab ne Klasse mit einer Template-Funktion die etwa so aussieht:
class Foo { public: template <class T> T* bar(const std::string&); }
"bar" lasse ich dabei absichtlich undefiniert, da ich nur das Ausführen von Template-Spezialisierungen dieser Method zulassen will:
template<> ExampleType* foo::bar(const std::string& whatever) { //blabla }
Zusaetlich befindet sich diese Klasse noch in 2 namespaces (outer::inner::foo).
Nur als Info: Einfach per Überladung kann ich das nicht machen, da die Signaturen der Methoden alle gleich sind. Außerdem macht Template-Spezialisierung es extrem einfach, für Benutzer der Bibliothek eigene "bars" einzufügen.
Im Moment habe ich 3 dieser Spezialisierungen, aber da werden mit der Zeit noch einige hinzukommen.
Zur Info: Ich benutze ganz normale Include-Guards, also verstehe ich nicht sorecht wieso die beiden Probleme überhaupt auftreten. Die Guards sehen in etwa so aus:
[cpp]
#ifndef LIBNAME_FOO_HPP
#define LIBNAME_FOO_HPP//...
#endif
Das Problem: In scheinbar zufälligen Intervallen nervt mich der Linker mit der Fehlermeldung, dass zwei oder mehrere Comdats für die gleiche Definition vorhanden sind (link fehlgeschlagen).
Das lässt sich dann nur beheben indem ich die betreffende Spezialisierung ändere, das kompilieren fehlschlagen lasse und anschließend wieder zurückändere und dann korrekt kompiliere. Wenn ich einfach so das ganze Projekt neukompiliere, bleibt der Fehler erhalten.
Ich habe schon gelesen, dass der Fehler auftreten kann wenn der Typname zu lang ist. OK, der Typname für den Compiler ist ziemlich lang (da er std::string aufklappen muss), aber mit Sicherheit keine 2047 Zeichen, welche die zugelassene Standardgröße für den Linker ist. Außerdem würde das nicht erklären, wieso das Problem näch Änderung und neukompilierung des Codes weggeht.
Zweites Problem:
Trotz der Include-Guards beschwerte sich der Linker über mehrfache Definitionen aller Spezialisierungen. Da ab da nicht mehr weiterzuarbeiten war kompiliere ich seitdem mit der Linker-Option "/Force:Multiple", was dazu führt dass der Linker einfach nur die erste Definition des Objekts nimmt und die restlichen ignoriert.
Das bringt jedoch andere Probleme mit sich: Wenn ich in den templates was ändere, werden die Änderungen nicht mitgelinkt, da schon von alten Kompiliervorgängen .obj Dateien da sind in der noch die alte Version steht. Und da diese zuerst kamen benutzt der VSLinker diese natürlich und ignoriert die neuen. Dagegen hilft dann nur ein komplettes Neu-kompilieren des Projekts, was schon extrem nervig ist, da das mittlerweile auch schon ca. 30 Sek dauert und in Zukunft sicher nicht schneller werden wird.
Ist das ein Bug in VS2010 und sollte ich auf 2008 zurückwechseln? Oder mach ich etwas falsch?
-
Hallo.
Ich hab die Spezialisierungen inline gemacht, jetzt verschwindet der Fehler und tritt nicht mehr auf.
Ich hab auch das ganze Projekt nochmal neu aufgesetzt seit ich die Frage gestellt hab (Gott was f[r ne Frimelarbeit).
Lustigerweise verbraucht das Programm jetzt ein Zehntel des benötigten Speichers wie das alte Programm
Das scheint wohl ein VS Bug gewesen zu sein, und da das alte Projekt noch nicht mit SP1 erstellt wurde, schätze ich dass das ganze in SP1 gefixed wurde.