Templateklasse soll je nach Typ unterschiedliche Member-Funktionen aufrufen
-
Danke für den Input!
otze schrieb:
Also du musst dich entscheiden, welche der beiden Funktionen die "normale" abarbeitung sein soll, und dann die Klasse nochmal für den anderen typen (zum Beispiel double) implementieren.
Äh, so:
template <typename T> bool FlightStatusData<T>::poll() { cout << "Called with not-double"; //Tu was } template <> bool FlightStatusData<double>::poll() { cout << "Called with double"; // Tu was anderes }??
Das geht auch nicht. Die andere Lösung sieht zwar auch gut aus, ist mir aber zu umständlich, wenn auch das geht, was ich zitiert habe.
-
Ne sorry, das funktioniert. Es war irgendein Compiler der das nicht wollte. hab das grad nochmal nachgeschaut:
post aus comp.lang.c++.moderateddeine Lösung sollte funktionieren. Die Lösung von oben brauchst du, wenn die methode selbst ein template ist.(Die template regeln sind viel zu komplex btw)
-
otze schrieb:
deine Lösung sollte funktionieren. Die Lösung von oben brauchst du, wenn die methode selbst ein template ist.(Die template regeln sind viel zu komplex btw)
Tut sie leider nicht. Quellcode wie oben, Fehlermeldung:
In function `A<double>::poll()': /home/philipp/.eclipse/test/Debug/../src/a.cpp:77: multiple definition of `A<double>::poll()' ./src/a.o:/home/philipp/.eclipse/test/Debug/../src/a.cpp:77: first defined here collect2: ld returned 1 exit status
-
Da es sich um nicht um Templatedefinitionen sondern um Funktionsdefinitionen handelt, ist nat. die ODR entsprechend zu beachten. Also die Definitionen aus dem Header raus (dort müssen dann aber die Spezialisierungen weiterhin deklariert werden, um die implizite Instantiierung zu unterdrücken!). Oder man macht die Funktionen schlicht inline.
Korrektur: die SPezialisierungen müssen nur dann im Header deklariert werden, wenn die Memberunktion bereits unspezialisiert definiert wurde.
-
camper schrieb:
Da es sich um nicht um Templatedefinitionen sondern um Funktionsdefinitionen handelt, ist nat. die ODR entsprechend zu beachten. Also die Definitionen aus dem Header raus (dort müssen dann aber die Spezialisierungen weiterhin deklariert werden, um die implizite Instantiierung zu unterdrücken!). Oder man macht die Funktionen schlicht inline.
Korrektur: die Spezialisierungen müssen nur dann im Header deklariert werden, wenn die Memberunktion bereits unspezialisiert definiert wurde.Ähh?
Das verstehe ich jetzt nicht. Diese Definitionentemplate <typename T> bool FlightStatusData<T>::poll() { cout << "Called with not-double"; //Tu was } template <> bool FlightStatusData<double>::poll() { cout << "Called with double"; // Tu was anderes }stehen im .cpp-File, nicht imn h-file.
Was muss ich aus dem h-file rausnhemen/ hinzufügen?
-
Zeig mal den relevanten Code, einschließlich der Angabe was wo inkludiert wird.
-
camper schrieb:
Zeig mal den relevanten Code, einschließlich der Angabe was wo inkludiert wird.
Also Header flightstatusdata.h:
#ifndef FLIGHTSTATUSDATA_H #define FLIGHTSTATUSDATA_H #include "XPLMDataAccess.h" #include "crittype.h" #include <QtGlobal> #include <QString> template <typename T> class FlightStatusData{ public: FlightStatusData(qint8 pid, const QString& name, const QString& DataRef, int crit = Crittype::Uncritical); FlightStatusData(); ~FlightStatusData(); qint8 id(); T data(); bool poll(); /*weiteres Zeug..*/ private: bool changeValue(T data); T m_data;/*weiteres Zeug*/ };cpp-file:
#include "flightstatusdata.h" #include "XPLMDisplay.h" #include "XPLMUtilities.h" #include "XPLMProcessing.h" #include "XPLMDataAccess.h" #include "config.h" #include <iostream> template <typename T> FlightStatusData<T>::FlightStatusData(): m_id(0), m_data(0), m_name(""), // weitere Initialisierungen { } template <typename T> FlightStatusData<T>::FlightStatusData(qint8 id, const QString& name, const QString& dataRef, int crit): m_id(id), m_data(0), // einige weitere initialisierungen { } template <typename T> FlightStatusData<T>::~FlightStatusData() { } template <typename T> qint8 FlightStatusData<T>::id() { return m_id; } template <typename T> T FlightStatusData<T>::data() { return m_data; } // usw usw .... //jetzt kommt der casus knacksus: template <typename T> bool FlightStatusData<T>::poll() { std::cout << "Called with not-double, probably int"; return changeValue((int)XPLMGetDatai(m_defDataRef)); } template <> bool FlightStatusData<double>::poll() { std::cout << "Called with double"; return changeValue((double)XPLMGetDataf(m_defDataRef)); } // weitere private Funktionen ...Main - Zwecks testen:
#include "flightstatusdata.h" #include <iostream> int main() { FlightStatusData<int>* fs = new FlightStatusData<int>(); fs-> poll(); delete fs; fs=0; std::cout << "Finish"; }
-
Du mußt alle Template-Definitionen in der Header-Datei definieren (bzw. von dort aus eine Datei inkludieren), jedoch die Definitionen der Spezialisierungen gehören (wegen der ODR) in eine CPP-Datei.
// in Header-Datei (direkt oder indirekt) template <typename T> FlightStatusData<T>::Method(...) { } // in Source-Datei template <> bool FlightStatusData<double>::poll() { }Die Fehlermeldung des Linkers deutet irgendwie darauf hin, als ob du die CPP-Datei mehrmals eingebunden (inkludiert) hast.
Edit: Rechtschreibung...
-
Hey, klasse. Dankeschön.
Hab jetzt alle unspezialisierten Funktionen in eine Datei *.impl gepackt und diese an das Ende des Headers includiert.
Die spezialiserten Funktionen stehen in der .cpp und jetzt fluppts!Is schon schlimm wenn man es anders gewöhnt ist. Son Chaos gibt's in Java nicht. Da gibt's halt Genrics und keine Templates. Von der Idee her ähnlich, aber eben doch von der Implementierung was völlig anderes.
Dankeschön an alle die zur Lösung des Problems beigetragen haben.
-
PhilippM schrieb:
Hey, klasse. Dankeschön.
Hab jetzt alle unspezialisierten Funktionen in eine Datei *.impl gepackt und diese an das Ende des Headers includiert.
Die spezialiserten Funktionen stehen in der .cpp und jetzt fluppts!Vergiss dann aber nicht, die Spezialisierungen in der *.impl-Datei zu deklarieren. Eine andere Möglichkeit als die Implementation im Header (bzw. .impl - was auf das Gleiche hinausläuft) besteht dann, wenn alle möglichen Tamplateargumente bekannt sind. Dann kann man die Implementation auch wie gewohnt in der .cpp-Datei stehen lassen und dort für alle Argumente instantiieren.