Klassentemplate konstruktor spezialisierung
-
Hallo,
ich habe folgendes Problem. Ich habe ein Klassentemplate
template < typename T> class vec3 { Vec3(const T& v) { x = y = z = v; } };Nun brauche ich aber noch einen Konstruktor für einen bestimmten Datentypen à la:
Vec3(const Vector& v) { x = v(0); y = v(1); z = v(2); }Logischerweise beschwert sich der Compiler dass der Konstruktor schon definiert ist. Nun meine Frage, kann ich diesen Konstruktor spezialisieren ohne die komplette Klasse zu spezialisieren? Und falls nicht, was habe ich für optionen?
Vielen Dank
-
template<typename T> struct vec_3 { typedef T value_type; vec_3(value_type v) { //der sinn hier ist natürlich fraglich... x = y = z = v; } vec_3(const vec_3& v) { x = v.x; y = v.y; z = v.z; } template<typename U> vec_3(const vec_3<U>& v) { x = static_cast<value_type>(v.x); y = static_cast<value_type>(v.y); z = static_cast<value_type>(v.z); } private: value_type x, y, z; }; int main() { vec_3<int> a(3); vec_3<int> a_(a); vec_3<double> b(a); }geht doch - oder habe ich dich falsch verstanden?
bb
-
unskilled schrieb:
geht doch - oder habe ich dich falsch verstanden?
Danke erstmal.
Ja da hast du mich falsch verstanden. Es geht nicht darum den gleichen Typen, also Vec3 (ob nun mit anderem templateparameter oder nicht) dem Konstruktor zu übergeben (das ghet ja auch bei mir), sondern einen komplett anderen Typen der nunmal Vector heisst (es ist eine andere Vector definition. Vector im sinne einer position im dreidimensionalen Raum).
Ungefähr so (obwohl das wahrscheinlich quatsch ist, aber es soll verdeutlichen was ich meine):
template<Vector> vec_3(const Vector& v) { x = static_cast<value_type>(v.x); y = static_cast<value_type>(v.y); z = static_cast<value_type>(v.z); }Ist das so verständlicher? thx
-
unskilled schrieb:
vec_3(value_type v)
{ //der sinn hier ist natürlich fraglich...
x = y = z = v;
}
[/cpp]Um deine zweifel mal zu erörtern, ein dreidimensionaler Vektor wird manchmal nunmal über einen skalar konstruiert.
-
Ach mist, ich glaube das geht aber trotzdem, wenn ich einfach den Template parameter U (in deinem Beispiel) nicht als Vec_3<U> verwende sondern einfach nur U.
Also:
template< typename U > vec_3(const U& v) { x = static_cast<value_type>(v.x); y = static_cast<value_type>(v.y); z = static_cast<value_type>(v.z); }Zumindest meckert der Compiler nicht mehr. Weiß jemand ob das Standardkonform ist?
Danke dir unskilled, das wäre zumindest der richtige Hinweis gewesen!
-
Katachi schrieb:
Ach mist, ich glaube das geht aber trotzdem, wenn ich einfach den Template parameter U (in deinem Beispiel) nicht als Vec_3<U> verwende sondern einfach nur U.
Also:
template< typename U > vec_3(const U& v) { x = static_cast<value_type>(v.x); y = static_cast<value_type>(v.y); z = static_cast<value_type>(v.z); }Zumindest meckert der Compiler nicht mehr. Weiß jemand ob das Standardkonform ist?
Danke dir unskilled, das wäre zumindest der richtige Hinweis gewesen!jopp - das ist korrekt.
-
super danke!

-
Katachi schrieb:
unskilled schrieb:
vec_3(value_type v)
{ //der sinn hier ist natürlich fraglich...
x = y = z = v;
}
[/cpp]Um deine zweifel mal zu erörtern, ein dreidimensionaler Vektor wird manchmal nunmal über einen skalar konstruiert.
nicht wirklich...
ist genau so sinnfrei, wie ein dreieck mit einem skalar zu konstruieren...bb
@Katachi:
Über den static_cast dort lässt sich natürlich streiten - so sieht man nämlich nicht, dass man - vll versehentlich - nachkommastellen abschneidet bzw aus dem wertebereich herauskommt oder oder oder - eben alle nachteile, die eine typkonversation mit sich bringen...
-
unskilled schrieb:
nicht wirklich...
ist genau so sinnfrei, wie ein dreieck mit einem skalar zu konstruieren...Es geht dabei auch nicht um den Sinn als viel mehr um eine bequeme Weise eine Koordinate (bspw. 1/1/1) zu initialisieren. Es ist wohl mehr als gängig und einfach praktischer Vec3(1.f) zu schreiben als Vec3(1.f,1.f,1.f). Ein Dreieck ist auch nicht wirklich damit vergleichbar. Oder was willst du damit sagen?
unskilled schrieb:
@Katachi:
Über den static_cast dort lässt sich natürlich streiten - so sieht man nämlich nicht, dass man - vll versehentlich - nachkommastellen abschneidet bzw aus dem wertebereich herauskommt oder oder oder - eben alle nachteile, die eine typkonversation mit sich bringen...Ich habe das jetzt komplett verworfen und mir ein paar inline funktionen zur Konvertierung geschrieben.
-
Katachi schrieb:
unskilled schrieb:
nicht wirklich...
ist genau so sinnfrei, wie ein dreieck mit einem skalar zu konstruieren...Es geht dabei auch nicht um den Sinn als viel mehr um eine bequeme Weise eine Koordinate (bspw. 1/1/1) zu initialisieren. Es ist wohl mehr als gängig Vec3(1.f) zu schreiben als Vec3(1.f,1.f,1.f). Oder was willst du damit sagen?
wenn ich also einen vektor(1,1,1) haben will und ich lieber 4 zeichen sparen will, nehm ich unleserlichen code in kauf?
was ist, wenn ich als nutzer einen ctor á la:explicit vec_3(const value_type& x = value_type(), const value_type& y = value_type(), const value_type& z = value_type()) : x(x), y(y), z(z) {}erwarte?
dann kann ich nämlich den 3d-vektor auch für 2d sachen nehmen...
wenn ich also vec(1) schreibe würde ich erwarten, danach(1, T(), T())- also(1, 0, 0)zu haben.bb
-
unskilled schrieb:
wenn ich also einen vektor(1,1,1) haben will und ich lieber 4 zeichen sparen will, nehm ich unleserlichen code in kauf?
Was für unleserlichen Code? Also ich programmiere jetzt seit 10 Jahren in der 3D Branche und so einen Unfug hab ich bisher noch nicht gehört. Wenn jemand mit convenience funktionen probleme, dann zweifel ich an seiner praktischen Erfahrung. Ich habe, zumindest in meiner Branche, noch keine vektorklasse gesehen die ohne skalarkonstruktor arbeitet..und auch zu recht.
was ist, wenn ich als nutzer einen ctor á la:
explicit vec_3(const value_type& x = value_type(), const value_type& y = value_type(), const value_type& z = value_type()) : x(x), y(y), z(z) {}erwarte?
Ich habe keine Nutzer. Ich schreibe an meiner eigenen Software. Und natürlich gibt es auch einen konstruktor der entsprechend drei skalare erwartet. Ich verstehe nicht wirklich worauf du hinaus willst.
dann kann ich nämlich den 3d-vektor auch für 2d sachen nehmen...
wenn ich also vec(1) schreibe würde ich erwarten, danach(1, T(), T())- also(1, 0, 0)zu haben.bb
Also wenn du für 2d sachen einen 3d vektor verwendest dann verschwendest du nutzlosen Speicher. Es gibt dafür 2d vektoren. Das passiert also erst gar nicht und macht auch wenig Sinn.
-
Hm, also ich halt auch nicht wirklich viel davon einen Vektor über ein Skalar zu "konstruieren".
Was unleserlicher code ist, sei mal dahingestellt, aber
vec_3(5).dotproduct(vec_3(3,4,5));oder
vec_3(5).crossproduct(vec_3(3,4,5).transpose());sieht für mich nicht mehr allzu intuitiv aus.
Warum sollte man keine 3D-Vektoren für 2D-Darstellungen verwenden dürfen bzw. können. Selbstverständlich muss das gewährleistet sein.
-
Immerhin ist so
Vec3(1,2,3) + Vec(4,3,2) == 5
-
Michael E. schrieb:
Immerhin ist so
Vec3(1,2,3) + Vec(4,3,2) == 5
Nö

Vec3(1,2,3) + Vec3(4,3,2) == Vec3(5)
-
Ich hab beim TO kein explicit gesehen - also war es mit
== 5schon richtig : Pbb
-
Mal ernsthaft: Wie oft benötigt man den 1-parametrigen Konstruktor, der alle drei Komponenten mit dem gleichen Wert füllt?
Sowas wird meines Erachtens für vor allem für
Scale()-Funktionen missbraucht, wenn sich ein Objekt in alle Richtungen gleichmässig skalieren soll. Aber der Fehler liegt mehr bei der nicht vorhandenenScale()-Überladung als im Vektor...Ach ja, und schau dir nichts bei den Vektorklassen von grossen Grafikframeworks wie Ogre3D ab. Deren Design ist äusserst katastrophal.