templates
-
Ich muß doch noch mal was zu templates fragen
Ich habe hier die .h meiner Mathe-Klasse, wobei die Structs vorher eindeutig mit double gebaut waren.
Nun sollen die Methoden aber auch float zulassen, so daß ich mir gedacht hatte das es ja geschickt wäre den Datentyp schon dort nicht festzulegen.#ifndef MATH_AMT_H #define MATH_AMT_H #include <iostream.h> #include <math.h> #define PI 3.14159265 // Ein Vektor aus drei Werten template <class T> struct vector3AMT { T v1; T v2; T v3; }; // Ein Vektor aus vier Werten template <class T> struct vector4AMT { T v1; T v2; T v3; T v4; }; // Eine 3x3 Matrix aus 3 Vektoren template <class T> struct matrix3x3AMT { vector3AMT <T> x; vector3AMT <T> y; vector3AMT <T> z; }; // Eine 4x3 Matrix aus 4 Vektoren template <class T> struct matrix4x3AMT { vector3AMT <T>x; vector3AMT <T>y; vector3AMT <T>z; vector3AMT <T>p; }; class Math_amt { public: Math_amt(); ~Math_amt(); matrix4x3AMT compTMatrixEuler(double positionX, double positionY, double positionZ, double eulerW1, double eulerW2, double eulerW3); matrix4x3AMT compTMatrixJawPitchRoll(double positionX, double positionY, double positionZ, double jawpitchrollW3, double jawpitchrollW2, double jawpitchrollW1); matrix4x3AMT compTMatrixQuaterionen(vector4AMT quaterionRotations, vector3AMT position); matrix3x3AMT compTMatrixQuaterionen(vector4AMT quaterionRotations); matrix4x3AMT mult4X3Matrix(matrix4x3AMT<double> aMatrix4x3, matrix4x3AMT bMatrix4x3); matrix4x3AMT invert4x3TMatrix(matrix4x3AMT tMatrix4x3); matrix4x3AMT getDIdentityTMatrix(); vector3AMT sub3VectorNorm(vector3AMT a, vector3AMT b); vector3AMT crossProduct3Vector(vector3AMT a, vector3AMT b); double det3x3Matrix(matrix3x3AMT matrix); vector3AMT add3VectorNorm(vector3AMT a, vector3AMT<double> b); vector3AMT cramer3x3Matrix(matrix3x3AMT matrix, vector3AMT ergebnisLGS); double pointDistance(vector3AMT a, vector3AMT b); };
Nun müsste ich aber bei den Methoden schon angeben welche Datentyp sie benutzten sollen das möchte ih aber ja gar nicht.
Gibt es da auch eine andere Möglichkeit??Gruß mkgandalf ( hoffe meine Frage ist klar formuliert)
-
// Eine 4x3 Matrix aus 4 Vektoren template <class T> struct matrix4x3AMT { typedef T MType; vector3AMT <T>x; vector3AMT <T>y; vector3AMT <T>z; vector3AMT <T>p; }; matrix4x3AMT compTMatrixEuler(matrix4x3AMT::MType positionX, matrix4x3AMT::MType positionY, matrix4x3AMT::MType positionZ, matrix4x3AMT::MType eulerW1, matrix4x3AMT::MType eulerW2, matrix4x3AMT::MType eulerW3);
Meinst du sowas ?
du musst aber das template definieren, befor es ausserhal verwendest, da deine Funktion compiliert werden will. und compilieren geht nur, wenn den typ weisst ....
Also kannst die funktion am ende eh auch nur als template machen ... wenn den typ variabel haben willst ....
also so in der art :
template<class T> matrix4x3AMT<T> compTMatrixEuler(matrix4x3AMT<T>::MType positionX, matrix4x3AMT<T>::MType positionY, matrix4x3AMT<T>::MType positionZ, matrix4x3AMT<T>::MType eulerW1, matrix4x3AMT<T>::MType eulerW2, matrix4x3AMT<T>::MType eulerW3);
kannst deine funktionen ned an deine template(klassen) hanegen ?
Ciao ...
-
...
-
meine Problem ist das die Mathe-Klasse im Prinzip schon da war und ich es nun so umbiegen will, das es ihm egal ist ob float oder double
hier die Klasse selbst
#include "Math_amt.h" /**************************************************************************** ** Konstruktor ****************************************************************************/ Math_amt::Math_amt() { //nothing to do } /***************************************************************************** ** Destruktor *****************************************************************************/ Math_amt::~Math_amt() { } /********************************************************************************** ** begin_Methoden **********************************************************************************/ // Euler-angles in degrees with: w1 for z-axis, w2 for x-axis, w3 for z-axis matrix4x3AMT Math_amt::compTMatrixEuler(double pX, double pY, double pZ, double w1, double w2, double w3) { double w1rad = w1/180.0 * PI; double w2rad = w2/180.0 * PI; double w3rad = w3/180.0 * PI; matrix4x3AMT mt; mt.x.v1 = (cos(w1rad) * cos(w3rad)) - (sin(w1rad) * cos(w2rad) * sin(w3rad)); mt.y.v1 = -(cos(w1rad) * sin(w3rad)) - (sin(w1rad) * cos(w2rad) * cos(w3rad)); mt.z.v1 = (sin(w1rad) * sin(w2rad)); mt.x.v2 = (sin(w1rad) * cos(w3rad)) + (sin(w1rad) * cos(w2rad) * sin(w3rad)); mt.y.v2 = -(sin(w1rad) * sin(w3rad)) + (cos(w1rad) * cos(w2rad) * cos(w3rad)); mt.z.v2 = -(cos(w1rad) * sin(w2rad)); mt.x.v3 = (sin(w2rad) * sin(w3rad)); mt.y.v3 = (sin(w2rad) * cos(w3rad)); mt.z.v3 = cos(w2rad); mt.p.v1 = pX; mt.p.v2 = pY; mt.p.v3 = pZ; return mt; } // JawPitchRoll-angles in degrees with: w3 for x-axis, w2 for y-axis, w1 for z-axis matrix4x3AMT Math_amt::compTMatrixJawPitchRoll(double pX, double pY, double pZ, double w1, double w2, double w3) { double w1rad = w1/180.0 * PI; double w2rad = w2/180.0 * PI; double w3rad = w3/180.0 * PI; matrix4x3AMT mt; /*mt.x.v1 = cos(w1rad)*cos(w2rad); mt.x.v2 = sin(w1rad)*cos(w3rad) + cos(w1rad)*sin(w2rad)*sin(w3rad); mt.x.v3 = sin(w1rad)*sin(w3rad) - cos(w1rad)*sin(w2rad)*cos(w3rad); mt.y.v1 = -sin(w1rad)*cos(w2rad); mt.y.v2 = cos(w1rad)*cos(w3rad) - sin(w1rad)*sin(w2rad)*sin(w3rad); mt.y.v3 = cos(w1rad)*sin(w3rad) + sin(w1rad)*sin(w2rad)*cos(w3rad); mt.z.v1 = sin(w2rad); mt.z.v2 = -cos(w2rad)*sin(w3rad); mt.z.v3 = cos(w2rad)*cos(w3rad); mt.p.v1 = pX; mt.p.v2 = pY; mt.p.v3 = pZ; */ mt.x.v1 = cos(w3rad)*cos(w2rad); mt.y.v1 = -sin(w3rad)*cos(w1rad) + cos(w3rad)*sin(w2rad)*sin(w1rad); mt.z.v1 = sin(w3rad)*sin(w1rad) + cos(w3rad)*sin(w2rad)*cos(w1rad); mt.x.v2 = sin(w3rad)*cos(w2rad); mt.y.v2 = cos(w3rad)*cos(w1rad) + sin(w3rad)*sin(w2rad)*sin(w1rad); mt.z.v2 = -cos(w3rad)*sin(w1rad) + sin(w3rad)*sin(w2rad)*cos(w1rad); mt.x.v3 = -sin(w2rad); mt.y.v3 = cos(w2rad)*sin(w1rad); mt.z.v3 = cos(w2rad)*cos(w1rad); mt.p.v1 = pX; mt.p.v2 = pY; mt.p.v3 = pZ; return mt; } // Multiplilation 2er 4x3 Matrizen matrix4x3AMT Math_amt::mult4X3Matrix(matrix4x3AMT aMat, matrix4x3AMT bMat) { matrix4x3AMT mt; mt.x.v1 = aMat.x.v1 * bMat.x.v1 + aMat.y.v1 * bMat.x.v2 + aMat.z.v1 * bMat.x.v3; mt.x.v2 = aMat.x.v2 * bMat.x.v1 + aMat.y.v2 * bMat.x.v2 + aMat.z.v2 * bMat.x.v3; mt.x.v3 = aMat.x.v3 * bMat.x.v1 + aMat.y.v3 * bMat.x.v2 + aMat.z.v3 * bMat.x.v3; mt.y.v1 = aMat.x.v1 * bMat.y.v1 + aMat.y.v1 * bMat.y.v2 + aMat.z.v1 * bMat.y.v3; mt.y.v2 = aMat.x.v2 * bMat.y.v1 + aMat.y.v2 * bMat.y.v2 + aMat.z.v2 * bMat.y.v3; mt.y.v3 = aMat.x.v3 * bMat.y.v1 + aMat.y.v3 * bMat.y.v2 + aMat.z.v3 * bMat.y.v3; mt.z.v1 = aMat.x.v1 * bMat.z.v1 + aMat.y.v1 * bMat.z.v2 + aMat.z.v1 * bMat.z.v3; mt.z.v2 = aMat.x.v2 * bMat.z.v1 + aMat.y.v2 * bMat.z.v2 + aMat.z.v2 * bMat.z.v3; mt.z.v3 = aMat.x.v3 * bMat.z.v1 + aMat.y.v3 * bMat.z.v2 + aMat.z.v3 * bMat.z.v3; mt.p.v1 = aMat.x.v1 * bMat.p.v1 + aMat.y.v1 * bMat.p.v2 + aMat.z.v1 * bMat.p.v3 + aMat.p.v1 * 1; mt.p.v2 = aMat.x.v2 * bMat.p.v1 + aMat.y.v2 * bMat.p.v2 + aMat.z.v2 * bMat.p.v3 + aMat.p.v2 * 1; mt.p.v3 = aMat.x.v3 * bMat.p.v1 + aMat.y.v3 * bMat.p.v2 + aMat.z.v3 * bMat.p.v3 + aMat.p.v3 * 1; return mt; } ....
Meine erst Idee war, das man einfach alle Methoden zweimal implementiert sowohl mit float als auch mit double, da das aber ja kein schöner Stil ist hat mir jemand was von den Templates erzählt
tja und nun steh ich da und versuche das anzupassen
gruß mkgandalf
-
tja, dann such nach den richtigen Dingen ...
Klassen mit variablen Typen = template Klassen
Funktionen mit variablen Typen (worunter auch variable(template)klassen zaehlen) = Template Funktionen.Und schau dir die Philosophie von Templates genauer an ... dann verstehst auch, warum gewisse dinge ned so einfach funktionieren koennen. Das heisst ned, das man es nicht doch hinbekommen koennt ....
Tip: Alles was keinen konkreten typ hat, kann der compiler ned compileren. Wie soll er wissen, wieviel speicherplatz er fuer nen unbekannten datentyp reservieren soll ....
Ciao ...
-
Ich machs am Beispiel einer Methode, den Rest kannste dann selbst:
class Math_amt { public: Math_amt(); ~Math_amt(); template <typename T> matrix4x3AMT<T> compTMatrixEuler(T positionX, T positionY, T positionZ, T eulerW1, T eulerW2, T eulerW3); };
Der Aufruf ist dann nachher wie gehabt, bei Funktionen und Methoden löst er die Template-Parameter, die auch in der normalen Parameterliste stehen, automatisch auf. Übrigens wäre es evtl. noch sinnvoller, T const & statt T zu schreiben. für den Fall, dass du das mal mit komplexeren Typen benutzen willst.
-
Was ist denn der Sinn dieser Math_amt-Klasse? Sieht aus wie eine reine Sammlung von Funktionen, nicht wie ein Datentyp. Löse die Klasse auf, oder mach die Funktionen wenigstens statisch.
-
Bashar schrieb:
Was ist denn der Sinn dieser Math_amt-Klasse? Sieht aus wie eine reine Sammlung von Funktionen, nicht wie ein Datentyp. Löse die Klasse auf, oder mach die Funktionen wenigstens statisch.
Also im Prinzip hast du recht es ist eine reine Sammlung von Funktionen bei denen es um Koordinatentranformation und ähnliches geht. Diese Matheklasse ist eigentlich Teil eines anderen Projektes und ich muß sie nun so anpassen das sie in beiden Projekten sowohl mit float als auch mit double Parametern läuft.
Erst wollte ich halt alle Methoden doppelt implementieren und auch die Structs, was aber kein wirklich guter Stil ist und auch schlecht wartbar.
Deswegen war halt mein erster Gedanke die Structs schon allgemeiner zu halten was sich aber mit dem anderen Aufbau als gar nicht so einfach erweist.
statisch machen ist mir glaub ich klar. Ich schreibe ford die MEthoden einfach noch static und kann dann mit Math_amt::methode darauf zugreifen aber wie löse ich die Klasse auf?@0xdeadbeef
ja das habe ich versucht und der Compiler meckert jetzt auch nicht mehr über die .h aber die cpp mag er nicht oder hab ich das auch noch falsch verstanden und es darf sie dann gar nicht mehr geben sonder das kommt alles in die .hGruß mkgandalf