static Methode in template Klasse
-
Hallo,
ich möchte eine static Methode in einer template Klasse haben:
namespace nml { template <class T> class Vector { private: T* data_; unsigned int size_; public: template <class T1, class T2> static double ScalarProduct(Vector<T1> v1, Vector<T2> v2); }; template <class T> template <class T1, class T2> static double Vector<T>::ScalarProduct(Vector<T1> v1, Vector<T2> v2) { return 0.0; } }Damit bekomme ich aber folgende Fehlermeldung:
Elementfunktion »static double nml::Vector<T>::ScalarProduct(nml::Vector<T1>, nml::Vector<T2>)« kann nicht deklariert werden, statische Bindung zu habenWarum geht das nicht?, oder was hab ich falsch gemacht?
Ich danke euch schonmal für eure Hilfe.
-
Das Schlüsselwort static nur in der Deklaration innerhalb des Klassenrumpfes verwenden. Bei der Definition außerhalb weglassen.
-
Vielen Dank für die schnelle Antwort. So einfach kanns sein.
Da hab ich gleich noch eine Frage zum Aufruf der static-Methode
nml::Vector<int> v(8); nml::Vector<int> u(8); double test = nml::Vector<int>::ScalarProduct(u,v);Kann man ScalarProduct auch irgendwie ohne Angabe des Templatearguments (hier int) aufrufen?, die Methode hängt von diesem ja eigentlich nicht ab.
-
Mach
ScalarProduktdoch als freie Funktion und dem Vektor gibts du eine Methode, mit welcher man auf die einzelnen Elemente zugreifen kann.Grüssli
-
Du meinst also, ich soll das ScalarProduct aus der Klasse raus nehmen?
Ist das nicht irgendwie blöd, weil semantisch gehört das SkalarProdukt doch zu den Vektoren. Deshalb wollte ichs eigentlich in der Klasse kapseln.Aber ich hab jetzt halt Probleme damit:
nml::Vector<int> v(8); nml::Vector<float> u(8); nml::Vector<int>::ScalarProduct(u,v)Ich kann im SkalarProdukt nicht auf die privaten Member von u zugreifen, weil u ein float-Vector ist.
Wie könnte man denn festlegen, dass alle Vector-Klassen(unabh. vom Templateargument) gegenseitig friends sind?
-
olibats schrieb:
Du meinst also, ich soll das ScalarProduct aus der Klasse raus nehmen?
Genau! Sonst definierst du nämlich auch zig Funktionen. Beispiel:
nml::Vector<int> v(8); nml::Vector<int> u(8); double test; test = nml::Vector<int>::ScalarProduct(u,v); test = nml::Vector<long>::ScalarProduct(u,v);Die beiden Funktionen machen das gleiche und haben die gleichen Parameter, sind aber nicht die gleichen Funktionen, da sie in unterschiedlichen Templateklassen sind! Daher eigentlich völliger Unsinn!
olibats schrieb:
Ist das nicht irgendwie blöd, weil semantisch gehört das SkalarProdukt doch zu den Vektoren. Deshalb wollte ichs eigentlich in der Klasse kapseln.
Wieso? Das Produkt hat nichts mit dem Vektor zu tun, das sind zwei unterschiedliche Dinge, welche man ganz klar voneinander trennen sollte. Schau dir als Beispiel die mathematischen Funktionen aus der Standardbibliothek an, das sind alles freie Funktionen und sind nicht irgendeinem Typ zugeordnet.
olibats schrieb:
Ich kann im SkalarProdukt nicht auf die privaten Member von u zugreifen, weil u ein float-Vector ist.
Wie könnte man denn festlegen, dass alle Vector-Klassen(unabh. vom Templateargument) gegenseitig friends sind?Wie ich schon vorhin geschrieben habe, brauchst du halt entsprechendet getter und setter.
int Vector<T>::count_elements() const; T const& Vector<T>::get_element(int iID) const; void Vector<T>::set_element(int iID, T const& rT);Oder so ähnlich. Um die ist man auch sonst froh!
Grüssli
-
OK, ich nehms aus der Klasse raus.
Ist das nicht ein Geschwindigkeitsnachteil, wenn ich auf jedes Element einzeln mit Get und Set zugreife?
-
olibats schrieb:
Ist das nicht ein Geschwindigkeitsnachteil, wenn ich auf jedes Element einzeln mit Get und Set zugreife?
Wenn du die Getter und Setter inline machst, dann eher nicht. Sowieso ist sowas an der falschen Stelle gespart, das macht extrem wenig aus.
Und wie würdest du es sonst macht? Du musst ja auch irgendwie auf die Elemente zugreifen. Ob das nun über eine Funktion passiert oder du direkt auf die Variablen zugreifst, dass ist so minim, dass es gar nicht messbar ist.Grüssli
-
Japp, ist es...
Ist zu vergleichen mit so was:
std::vector <int> arr (100); for (size_t i (0); i != 100; ++i) { arr[i]; } for (std::vector <int>::iterator i (arr.begin ()), end (arr.end ()); i != end; ++i) { *i; }Aber falls du die Vectoren bis jetzt auch nicht mit iteratoren durchgehst (oder sie nicht x-millionen-dimensionen haben sollte man das vernachlässigen können...
Für so was könnte man halt auch einfach 2 Public-Wrapper-Funktionen schreiben, wenn es sich später rausstellt, dass es jz viel zu langsam ist...
class xyz { private: std::vector <int> arr; public: std::vector <int>::iterator GetFirst () {arr.begin ();}; std::vector <int>::iterator GetEnd () {arr.end ();}; }dann sollte es eigtl keinen Unterschied mehr machen...
bb
-
Meine Idee wäre sonst noch gewesen, die SkalarProdukt-Methode als friend von der Vektor-Klasse zu definieren. Damit könnte ich dann direkt mit dem privaten Pointer arbeiten.
Bei den gettern und settern gibts eben bei jedem Zugriff einen Funktionsaufruf.
Aber mit inline müsste das natürlich gehen.Ich werde es gleich mal ausprobieren.
Vielen Dank euch erstmal für die Hilfe.