Templates und Linker-Probleme
-
Für ein Projekt habe mich mal intensiver mit Templates beschäftig und bin auf einige Fragen gestoßen.
Ich habe eine Klasse IOData:
IOData.h:
#pragma once #include <array> template<std::size_t Size> class IOData { public: IOData(void); ~IOData(void); double& operator[](unsigned Index); IOData<Size> operator=(IOData<Size> Right); private: std::tr1::array<double, Size> m_Array; };IOData.cpp:
#include "IOData.h" template<std::size_t Size> IOData<Size>::IOData(void) { } template<std::size_t Size> IOData<Size>::~IOData(void) { } template<std::size_t Size> double& IOData<Size>::operator[](unsigned Index) { return m_Array.at(Index); } template<std::size_t Size> IOData<Size> IOData<Size>::operator=(IOData<Size> Right) { m_Array = Right.m_Array; return (*this); } //Allgemeine binäre Operatoren template<std::size_t Size> IOData<Size> operator+(IOData<Size> Left, IOData<Size> Right) { IOData<Size> rtn = {0}; for(unsigned i = 0; i < Size; i++) rtn[i] = Left[i]+Right[i]; return rtn; } template<std::size_t Size> IOData<Size> operator-(IOData<Size> Left, IOData<Size> Right) { IOData<Size> rtn = {0}; for(unsigned i = 0; i < Size; i++) rtn[i] = Left[i]-Right[i]; return rtn; } template IOData<26>; //<----- HIERUM GEHT ESmain.cpp:
... IOData<26> RelativeHaeufigkeit(ifstream* Datei) { IOData<26> rtn; char a = 0; long count = 0; while(!Datei->eof()){ a = Datei->get(); if(a >= 97 && a <= 122) rtn[a-97]++; count++; } for(unsigned i = 0; i < 26; i++) rtn[i] = rtn[i] / count; return rtn; } ...Warum muss ich in der IOData.cpp unten noch ein "template IOData<26>;" einfügen. Ansonsten gibt es nämlich Linker Errors.
Es kann ja nicht sein, das ich jede spezielle Arraygröße erst bekannt machen muss.Oder missbrauche ich templates gerade für etwas, wofür es nicht gemacht ist?
MFG
Ace
-
(ohne den code gelesen zu haben)
templates kann man nicht in *.h und *.cpp aufteilen.
muss alles in der selben datei stehen.
bzw du nennst die source-datei in *.inl oder *.impl um und includest sie am ende des headers. aber anders geht es mit templates nichtbb
-
in folgendem Teil in der FAQ stehts (dritter Punkt):
http://www.c-plusplus.net/forum/viewtopic-var-t-is-246875.html
PS: das nächstemal am Besten gleich die Linkerfehler mit angeben

-
Hmm ok.
Alles klar.
Viele Dank
-
Hab wieder ein Problem mit selbiger Klasse:
Diesmal wollte ich den << operator für cout definieren, bekomme aber wieder einen Linker Fehler.iodata.hpp
#pragma once #include <array> #include <iostream> template<std::size_t Size> class IOData { public: IOData(void); ~IOData(void); double& operator[](unsigned Index); IOData<Size> operator=(IOData<Size> Right); friend std::ostream& operator<<(std::ostream& ostr, IOData<Size> &m); private: std::tr1::array<double, Size> m_Array; }; [...] //HIERUM GEHTS template<std::size_t Size> std::ostream& operator<<(std::ostream& ostr, IOData<Size> &m) { for(unsigned i = 0; i < Size; i++) ostr << m.m_Array[i] << " "; return ostr; }main.cpp
#include <iostream> #include "iodata.hpp" using namespace std; int main() { IOData<5> var; for(unsigned i = 0; i < 5; i++) var[i] = i; cout << var; return 1; }Error
1>------ Erstellen gestartet: Projekt: test, Konfiguration: Debug Win32 ------ 1> main.cpp 1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class IOData<5> &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$IOData@$04@@@Z)" in Funktion "_main". 1>c:...\test.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise. ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========Diesmal hab ich die Klasse ja in einer Datei... Wo ist der Fehler?
MFG
Ace
-
...
-
Du deklarierst eine Funktion (die friend-Deklaration in der Klasse) aber definierst sie nirgendswo. Diese Deklaration ist nämlich nicht kompatibel zu dem Template darunter. Das sind zwei verschiedene Dinge.
-
D.h. ich muss die Funktion in der Klassedeklaration definieren?
So gehts schonmal:
class IOData { public: IOData(void); ~IOData(void); double& operator[](unsigned Index); IOData<Size> operator=(IOData<Size> Right); friend std::ostream& operator<<(std::ostream& ostr, IOData<Size> &m) { for(unsigned i = 0; i < Size; i++) ostr << m.m_Array[i] << " "; return ostr; } private: std::tr1::array<double, Size> m_Array; };Danke
-
AceKiller73 schrieb:
D.h. ich muss die Funktion in der Klassedeklaration definieren?
Nö. Das heißt nur, dass Deine friend-Deklaration nicht zum Template passte.
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16
-
Ahh ok.
Danke...
Is aber auch verwirrend.