Probleme bei Funktions-Template Spezialisierung
-
Hallo Forum,
ich bin gerade dabei C++ zu lernen (Buch: Der C++ Programmierer).
Allerdings stoße ich bei einer Aufgabe auf Probleme, bzw. verstehe das Verhalten nicht.
Und zwar soll eine Template-Funktion "getType" den Variablentyp als String zurückgeben.
//main.cpp #include <iostream> #include <string> //#include "gettype.h" //#include "gettype_t.cpp" using namespace std; template <typename T> string getType(T t) { cout << "unb" << endl; } template <> string getType<int>(int t) { cout << "INT" << endl; } template <> string getType<unsigned int>(unsigned int t) { cout << "UI" << endl; } template <> string getType<char>(char t) { cout << "CH" << endl; } template <> string getType<bool>(bool t) { cout << "BL" << endl; } int main() { int i; cout << getType(i) << endl; unsigned int ui; cout << getType(ui) << endl; char c; cout << getType(c) << endl; bool b; cout << getType(b) << endl; float f; cout << getType(f) << endl; }Mir ist klar, dass ich hier keinen Wert zurückgebe und das Ergebnis direkt ausgebe, aber ich habe das nur zu Testzwecken so gemacht.
Die Fehlermelung lautet:
...\cppbuch\uebung3.10\main.cpp|11|multiple definition of `std::string getType<int>(int)'|
Warum wird die Funktion mehrere male definiert?
Und warum funktioniert das ohne Probleme wenn ich den Rückgabetyp ändere?:
template <typename T> int getType(T t) { cout << "unb" << endl; } template <> int getType<int>(int t) { cout << "INT" << endl; } template <> int getType<unsigned int>(unsigned int t) { cout << "UI" << endl; } template <> int getType<char>(char t) { cout << "CH" << endl; } template <> int getType<bool>(bool t) { cout << "BL" << endl; }Geht auch mit jedem anderen Typ.
IDE: Code::Blocks 13.12
Compiler: GNU GCC 4.8.2Eine Lösung wie es funktioniert habe ich dann auch nach Recherche im Inet gefunden. Und zwar wird die allgemeine Funktions-template in einem Header definiert und die Spezialisierungen nur deklariert und dann in einem separaten File definiert.
So:
#ifndef GETTYPE_H_INCLUDED #define GETTYPE_H_INCLUDED #include<string> template<typename T> std::string getType(T t) { return "Unbekannter Dateityp"; } template<> std::string getType(int); template<> std::string getType(unsigned int); template<> std::string getType(char); template<> std::string getType(bool); #endif // GETTYPE_H_INCLUDEDIch verstehe aber nicht ganz warum ich das so machen muss.
Danke für die Hilfe

-
Dein erstes Beispiel compiliert bei mir überhaupt nicht. Du musst schon mindestens ein
return string();einbauen. Dann funktioniert auch alles so wie es soll.
-
Dein Code passt nicht so ganz zur Fehlermeldung.
Aber dein zweiter Ansatz ist schon richtig.
Eine Templatespezialisierung ist kein Template mehr und folglich auch nicht implizit inline. Sie muss also entweder als inline gekennzeichnet werden oder in einer .cpp Datei definiert.
-
Nathan schrieb:
Eine Templatespezialisierung ist kein Template mehr
Hast du ganz im Ernst erwartet ich würde das einfach ignorieren?

-
Arcoth schrieb:
Nathan schrieb:
Eine Templatespezialisierung ist kein Template mehr
Hast du ganz im Ernst erwartet ich würde das einfach ignorieren?

Ich habe nicht an dich gedacht, als ich das geschrieben habe. :p
Jaja, natürlich ist eine Templatespezialisierung ein Template, nur halt nicht mehr inline.
-
Mensch_mit_Hut schrieb:
Eine Lösung wie es funktioniert habe ich dann auch nach Recherche im Inet gefunden. Und zwar wird die allgemeine Funktions-template in einem Header definiert und die Spezialisierungen nur deklariert und dann in einem separaten File definiert.
Nimm doch die Lösung zum Buch von der webseite und inkludiere
#ifndef GETTYPE_T #define GETTYPE_T #include <string> // Template template <typename T> std::string getType(T) { // Parametername wird nicht gebraucht return "unbekannter Typ"; } // Template-Spezialisierungen template <> std::string getType(int) { return "int"; } template <> std::string getType(unsigned int) { return "unsigned int"; } template <> std::string getType(double) { return "double"; } template <> std::string getType(char) { return "char"; } template <> std::string getType(bool) { return "bool"; } #endifin deinem main(). scheint mir das einfachste zu seim. und überall ist ein return.
-
Danke für die Antworten.
Habe jetzt verstanden woher die Fehlermeldung kam.
Die Lösung habe ich gesehen. Allerdings habe ich anstatt einer "gettype.t" eine "gettype_t.cpp" erstellt und diese dann in die "main.cpp" eingebunden
. Und bei meinen Versuchen war diese "gettype_t.cpp" immernoch im Projekt vorhanden.Wenn ich das richtig verstanden habe, werden so die Templates zweimal definiert (auch wenn es beides mal das gleiche ist), was nicht mit der One Definition Rule zusammenpasst.
Jetzt läuft das wie es sein sollte und ich bin etwas schlauer
