gcc bug mit templates?
-
Also, folgendes Problem. Ich habe mit Dev-C++ ein C++-Konsolenprojekt erstellt (mit mehreren Quelltextdateien) und auch die passenden Header dazugeschrieben. Das hat wunderbar funktioniert. Nun wollte ich ein Funktionstemplate machen und habe es so definiert:
// console.cpp template<class T> void logger(T output,unsigned short id = 0) { // ... cout<<output<<endl; }
und so deklariert:
// console.hpp template<class T> void logger(T output,unsigned short id); // Kein Default-Wert da man diese nur einmal deklarieren darf
Nun wollte ich dieses Template benutzen:
// main.cpp #define LOG_ERROR 1 //... include "console.hpp" //... logger("Fehler",LOG_ERROR); //...
Das müsste ja theoretisch gehen, oder? Beim kompilieren gibts auch keine Fehler, aber der Linker meckert rum:
[Linker error] Undefined reference to 'void logger<char const*>(char const*,unsigned short)' ... und mehr davon
Das verwundert mich schon ein bisschen, weil es ja eigentlich
void logger<const char*>(const char*,unsigned short)
heißen müsste.
Was soll ich tun
Danke schon mal im Voraus,
MfG Lars
PS: Es ist berechtigt, einen "Bug" im Compiler zu vermuten, weil
- Templates für den Compilerhersteller schwierig zu implementieren sind (ich verweise auf das Buch "C++ Kompedium" von M&T)
- ich schon mehrmals probleme mit gcc 3.4.2 gehabt habe (code funktioniert nicht, vor entsprechende stelle ein cout<<"Test"<<endl; gesetzt -> code funktioniert)
-
Die Templates musst du in der Headerdatei komplett schreiben. Das ist nicht wie bei Klassen.
-
wie meinst du das? das template in der headerdatei definieren?
-
PS: Es ist berechtigt, einen "Bug" im Compiler zu vermuten, weil
* Templates für den Compilerhersteller schwierig zu implementieren sind (ich verweise auf das Buch "C++ Kompedium" von M&T)
* ich schon mehrmals probleme mit gcc 3.4.2 gehabt habe (code funktioniert nicht, vor entsprechende stelle ein cout<<"Test"<<endl; gesetzt -> code funktioniert)in 99,9% aller Fälle sitzt das problem davor, wie jetzt auch.
templates gehören, solange der compiler kein export unterstützt in die header datei(der einzige compiler der export unterstützt ist der comeau).
dh, deine header datei sieht dann so aus:// console.hpp template<class T> void logger(T output,unsigned short id = 0) { // ... cout<<output<<endl; }
beim gcc ist mir bisher noch kein bug aufgefallen, dazu muss ich aber auch sagen, dass ich regelmäßig nach updates suche.
und auf ein M&T buch zu verweisen ist in etwa so sinnvoll, wie sich bei nem atomangriff untern tisch zu ducken, da die bücher größtenteils inhaltliche schwächen haben(void main/iostream.h/etc.pp)
-
habe ich in die headerdatei geschrieben und derselbe merkwürdige fehler kommt wieder (char const*)
btw: ein void main bzw. iostream.h ist mir bis jetzt noch nicht aufgefallen... ich werde aber noch einmal gründlich schauen
-
bleibt noch zu erwähnen, dass das template inline definiert werden sollte, sonst gibts linker fehler wenn dieselbe instanz in mehreren ÜEs benutzt wird.
-
camper schrieb:
bleibt noch zu erwähnen, dass das template inline definiert werden sollte, sonst gibts linker fehler wenn dieselbe instanz in mehreren ÜEs benutzt wird.
Käse.
-
@camper:
meinst duinline template<class T> void logger(T output,unsigned short id = 0)
?
selber fehler... ich wüsste auch nicht warum ich das machen sollte...
oder meinst du etwa die definition in meine klasse direkt reinzuschreiben? ich habe aber keine instanz einer klasse noch eine klasse selber erstellt. ich weiß auch nicht wo das irgendwo in diesem thread steht
-
Der Fehler, den du die ganze Zeit hast, wird nicht beim Kompilieren festgestellt, sondern erst beim Linken. Das bedeutet, dass dein Code korrekt kompiliert werden konnte.
Mach mal ein minimales funktionsfähiges, dass wir uns anschauen können. Mit deinen Fragmenten kann man nicht alles sehen.
-
zu der sache mit char const*:
char const* == const char*
-
@otze: gut zu wissen
@Ponto: genau das ist das problem. ich kann dir nur ein "minimal nicht funktionsfähiges" projekt von dev-c++ hier listen. also:Projekt aus 3 Dateien:
main.cpp
console.cpp
console.hpp(das ist mein projekt mit ausnahme aller funktionen und dateien, die 100% funktionieren)
// CONSOLE.CPP /* including: - user interface */ #include <iostream> using namespace std; #include "console.hpp" void prepare(int id) { switch (id) { case LOG_ERROR: { cout<<"ERROR: "; break; } case LOG_SUCCESS: { cout<<"SUCCESS: "; break; } case LOG_PROGRESS: { cout<<"PROGRESS: "; break; } } } template<class T> void logger(T output,unsigned short id = 0) { prepare(id); cout<<output<<endl; } //CONSOLE.HPP #include <iostream> #define LOG_ERROR 1 #define LOG_SUCCESS 2 #define LOG_PROGRESS 3 void prepare(int id); template<class T> void logger(T output,unsigned short id); //MAIN.CPP #include <iostream> using namespace std; #include "console.hpp" int main(int argc,char** argv) { logger("Test",LOG_ERROR); cin.get(); return 0; }
Ich glaube, der Rest an Dateien, die Dev-C++ angelegt hat, interessiert nicht, oder? (Projekt1.dev, .layout, ...)
-
//CONSOLE.HPP #include <iostream> //die defines sind zwar nicht falsch, aber wenn man mal dabei ist... enum states{ LOG_ERROR, LOG_SUCCESS, LOG_PROGRESS }; void prepare(states id); template<class T> void logger(T output,states id=LOG_ERROR) { prepare(id); std::cout<<output<<std::endl; }
//CONSOLE.CPP #include "console.hpp" using namespace std; void prepare(states id) { switch (id) { case LOG_ERROR: { cout<<"ERROR: "; break; } case LOG_SUCCESS: { cout<<"SUCCESS: "; break; } case LOG_PROGRESS: { cout<<"PROGRESS: "; break; } } }
//main.cpp #include "console.hpp" using namespace std; int main(int argc,char** argv) { logger("Test"); cin.get(); return 0; }
so funktionierts... erklärung siehe meinen ersten post.
-
so funktionierts eben nicht, und das ist das problem!
[Linker error] undefined reference ...
übrigens: danke für den tipp mit dem enum. mit dem kenne ich mich noch nicht so gut aus
-
hab nochmal editiert. mein gcc schluckt das so
-
das ist interessant... also ich benutze version 3.4.2 mit dev-c++ 4.9.9.2 (der gcc-compiler lag bei der beta-version mit bei) <-- kann das daran liegen (an der version)
-
Wie sieht deine .hpp genau aus, nachdem du otzes vorschlag reinkopiert hast? Und wie ist die Fehlermeldung genau?
-
updates für den mingw
-
@ponto:
console.hpp:#include <iostream> #define LOG_ERROR 1 #define LOG_SUCCESS 2 #define LOG_PROGRESS 3 void prepare(int id); template<class T> void logger(T output,unsigned short id = 0) { prepare(id); std::cout<<output<<endl; }
und das steht im kompilier log von dev-c++:
Compiler: Default compiler Building Makefile: "D:\Sicherung\Makefile.win" Führt make... aus make.exe -f "D:\Sicherung\Makefile.win" all g++.exe console.o main.o -o "Projekt1.exe" -L"C:/Dev-Cpp/lib" main.o(.text+0x13a):main.cpp: undefined reference to `void logger<char const*>(char const*, unsigned short)' collect2: ld returned 1 exit status make.exe: *** [Projekt1.exe] Error 1 Ausführung beendet
@otze: aber der 3.4.2 dürfte doch der neueste sein, oder nicht?
-
Hast du ein make clean gemacht? Lösch mal alle .o Dateien
-
habe alle .o's gelöscht, mehrmals
-
Lars Hupel schrieb:
habe alle .o's gelöscht, mehrmals
zeig das compile log, dass er wirklich alles kompiliert. in deinem letzten beispiel (dass übrigens nicht (alle) änderungen von otze drin hat) wird nämlich nicht alles kompiliert.