template vs virtual -- Basis-Klasse für Matrizen

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Dirty Oerti » Do Jan 17, 2013 1:54 am

Gleich noch eine Frage heute :)

Ich schreibe eine C++ Klassenhierarchie für Matrizen. Dabei habe ich eine Klasse Matrix, die mir sozusagen das Interface definiert, welches eine Matrix haben muss. Dann noch zwei erbende Klassen: ArrayMatrix und PointerMatrix, die beide eine Implementierung der in Matrix definierten Schnittstelle sind. Die eine arbeitet mit Array-Zugriffs-Methoden (also someArray[9]), die andere mit Zeigern. Der Sinn und Unsinn dahinter ist dabei nicht wichtig, es ist eine Übungsaufgabe in einem Fach an der Uni hier. Ziel ist letztendlich, die Implementierungen zu vergleichen (im Blick auf Ausführungsgeschwindigkeit etc).

Zur Schnittstelle: Eine Matrix muss die Addition mit einer weiteren Matrix unterstützen, außerdem die Multiplikation mit einer anderen Matrix und die Multiplikation mit einem Skalar. Und Letzteres ist der Punkt, an dem ich auf Probleme stoße.

Hier erstmal meine bisher so ausgearbeitete Klassen-Deklaration:

Code: Alles auswählen

namespace matrix
{
  template<typename T> class Matrix
  {
    public:
      virtual T & operator()(std::size_t, std::size_t) = 0;

      virtual Matrix<T> operator+ (Matrix<T> const &) = 0;
      virtual Matrix<T> operator- (Matrix<T> const &) = 0;
      virtual Matrix<T> & operator+= (Matrix<T> const &) = 0;
      virtual Matrix<T> & operator-= (Matrix<T> const &) = 0;

      virtual Matrix<T> operator* (Matrix<T> const &) = 0;
      virtual Matrix<T> & operator*= (Matrix<T> const &) = 0;

      template<typename X> virtual Matrix<T> operator* (X const &) = 0; /// ------------------ BOOM
      template<typename X> virtual Matrix<T> & operator*= (X const &) = 0; /// -------------BANG

      template<typename X,T> friend Matrix<T> operator* (X const &, Matrix<T> const &);
      template<typename X,T> friend Matrix<T> & operator*= (X const &, Matrix<T> const &);
  };

} // namespace matrix
Ich denke, was ich mir dabei so grundlegend gedacht habe, dürfte klar ersichtlich sein. An der Stelle, an der ich virtuelle template Methoden haben möchte klappt mir mein Konzept aber zusammen: Das wird nicht unterstützt, und mir ist auch klar und verständlich, warum.

Die Idee dieser Methoden ist die Folgende:
Ich habe eine Matrix, sagen wir mit dem Template Parameter int. Diese Matrix möchte ich nun gerne mit dem Skalar (Integer) 3 als auch mit dem Skalar (Double) 3.3456 multiplizieren können. Deshalb die Verwendung eines weiteren template Parameters. Denn verwende ich T (der Klassen-Template-Parameter), dann würde ich nur Skalare vom Typ Integer verwenden können.

Nun ist mir aber nicht so wirklich klar, wie ich das implementieren soll. Ich habe schon etwas von type erasure gelesen, vermute aber, dass ich das hier nicht anwenden kann, da ich ja eingebauten Typen wie int und double gegenüberstehe.

Ideen? Anregungen?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Xin » Do Jan 17, 2013 12:28 pm

Schau Dir mal den Quellcode an, den ich hier mal gepostet habe: Template-Templates, insbesondere die Add-Methode.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Dirty Oerti » Do Jan 17, 2013 5:24 pm

Hm, ich verstehe nicht so ganz, wie mir das weiterhilft. Ich verstehe, dass du mit deiner Klasse Container (wie der Name ja schon sagt) einen Behälter für deinen (Template) Datentyp schaffst.

Dann nutzt du diesen Container in deiner Add Methode, anstatt dem eigentlichen Datentyp.

Hm, keine Ahnung, was du mir damit sagen willst :D
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Xin » Do Jan 17, 2013 5:42 pm

Dirty Oerti hat geschrieben:Hm, ich verstehe nicht so ganz, wie mir das weiterhilft. Ich verstehe, dass du mit deiner Klasse Container (wie der Name ja schon sagt) einen Behälter für deinen (Template) Datentyp schaffst.

Dann nutzt du diesen Container in deiner Add Methode, anstatt dem eigentlichen Datentyp.

Hm, keine Ahnung, was du mir damit sagen willst :D
Mein Problem war, dass ich zwei addierbare Typen hatte - wie Du mit int und float.

Leider waren die Templates allerdings unterschiedlich, weil die Memory-Handler unterschiedlich waren. Ich konnte also einen Container<int, A> nicht mit einem Container<int, B> addieren, obwohl ich in beiden Fällen ja nur an das Int wollte.

Damit ich überhaupt in eine Funktion 'add' kommen konnte, die container< int, HandlerA > und container< int, HandlerB > verknüpfen konnte brauchte ich diese Template-Add-Funktion.
Mit der GetValue() bekomme ich also links wie rechts ein int zurück, egal welcher Handler benutzt wird und kann addieren.
operator + ist für zwei ints definiert. Das ganze kann also kompiliert werden. Das Ergebnis ist ein int, also wird ein neuer container für int angelegt.

Bei Deiner Matrix würdest Du ein int und ein float zurückbekommen - die kann man addieren - und einen neue Matrix anlegen dürfen. Dank C++11 kannst Du jetzt auch mit dekltype( int + float ) klar angeben, dass Deine Matrix eine Matrix<float> ist. Ich habe mich beim Handler einfach für den erstbesten entschieden, da das noch nicht mit decltype bestimmt werden konnte, bzw. über Spezialisierungen geregelt werden müsste.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Dirty Oerti » Do Jan 17, 2013 5:55 pm

Ich versteh es immer noch nicht :D
In wie weit hilft mir das auch beim virtual weiter? Oder brauche ich das dann nicht mehr?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Xin » Do Jan 17, 2013 7:52 pm

Dirty Oerti hat geschrieben:Ich versteh es immer noch nicht :D
In wie weit hilft mir das auch beim virtual weiter? Oder brauche ich das dann nicht mehr?
Keine Ahnung, wofür Du virtual brauchst. Virtual ist das Schlüsselwort für OOP und macht daher erst Sinn, wenn Du Klassen von den Template-Klassen ableitest, also mehrere Klassen einen gemeinsamen Basistyp haben.

Templates, also Klassengenerierung bedeutet, dass Du viele Klassen erzeugst, die in keinerlei Weise miteinander verwandt sind, sofern Du dem Template nicht eine Basisklasse verpasst, die von der keinem Templateparameter abhängig ist.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Dirty Oerti » Do Jan 17, 2013 10:11 pm

Xin hat geschrieben:Keine Ahnung, wofür Du virtual brauchst.
Naja, ich habe ja zwei verschiedene Implementierungen meiner Matrix. Also ist das genau der Fall:
Xin hat geschrieben:macht daher erst Sinn, wenn Du Klassen von den Template-Klassen ableitest, also mehrere Klassen einen gemeinsamen Basistyp haben.
Ich habe meine Matrix Klasse als gemeinsamen Basistyp von zwei anderen Klassen (ArrayMatrix und PointerMatrix).
Eine ArrayMatrix kann ich also auch als Matrix bezeichnen. Gleichzeitig möchte ich eine ArrayMatrix mit einem int oder auch einem double multiplizieren können. Allerdings möchte ich das auch bei einem Objekt, das ich nur als Typ Matrix referenziere.

Code: Alles auswählen

ArrayMatrix<int> a = ArrayMatrix<int>(3,3);
// set values of a
a *= 5;
a *= 3.14;
Matrix<int> b = a;
b *= 0.2;
b *= (1.0/3.14);
Das ist prinzipiel das Ziel.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Dirty Oerti » Do Jan 17, 2013 11:37 pm

Mir ist auch gerade noch etwas gekommen:

Schöner wäre es eigentlich, wenn ich der Matrix Variablen bei Deklaration nicht den Typ, den sie intern speichert mit auf den Weg geben muss, sondern die Matrix sich selbst um die korrekten Typen kümmert:

Code: Alles auswählen

ArrayMatrix a = ArrayMatrix(3,3);
a(0,0) = 1; // Element ist als int gespeichert
a(1,1) = 0.5; // Element ist als double/float gespeichert
a(0,0) *= 0.76; // Element ist NUN als double/float gespeichert

ArrayMatrix b = ArrayMatrix(3,3,NonChangingContainerFactory<int>());
b(0,0) = 2; // Element ist als int gespeichert
b(1,1) = 0.6; // Element ist als int gespeichert, also == 1
b(0,0) *= 1.6; // Element ist als int gespeichert, also == 3
Das wäre natürlich ziemlich krass ... :D Ich bin mir im Moment auch nicht sicher, ob das überhaupt möglich ist.

Wegen meinem Problem virtual vs template habe ich aber eine neue Idee:
Ich brauche virtual eigentlich nur, um gewisse Methoden unterschiedlich zu implementieren. Die Speicherung der Daten im Objekt ist identisch, und die Operator/Methoden-Deklaration ebenfalls. Da würde sich doch eigentlich ein Policy Design anbieten?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: template vs virtual -- Basis-Klasse für Matrizen

Beitrag von Xin » Sa Jan 19, 2013 12:14 pm

Dirty Oerti hat geschrieben:Mir ist auch gerade noch etwas gekommen:

Schöner wäre es eigentlich, wenn ich der Matrix Variablen bei Deklaration nicht den Typ, den sie intern speichert mit auf den Weg geben muss, sondern die Matrix sich selbst um die korrekten Typen kümmert:

Code: Alles auswählen

ArrayMatrix a = ArrayMatrix(3,3);
a(0,0) = 1; // Element ist als int gespeichert
a(1,1) = 0.5; // Element ist als double/float gespeichert
a(0,0) *= 0.76; // Element ist NUN als double/float gespeichert[/quote]
Moooment... Du willst pro Element zur Laufzeit Typen austauschen!?

[quote="Dirty Oerti"]Das wäre natürlich ziemlich krass ... :D Ich bin mir im Moment auch nicht sicher, ob das überhaupt möglich ist.[/quote]
Ich schon. Das werden viele Zeiger, die auf Klassen zeigen, die ints oder doubles wrappen und die Information enthalten, ob sie nun int oder double sind.
Nimm einfach double ;-)

[quote="Dirty Oerti"]Wegen meinem Problem virtual vs template habe ich aber eine neue Idee:
Ich brauche virtual eigentlich nur, um gewisse Methoden unterschiedlich zu implementieren. Die Speicherung der Daten im Objekt ist identisch, und die Operator/Methoden-Deklaration ebenfalls. Da würde sich doch eigentlich ein [url=http://en.wikipedia.org/wiki/Policy-based_design]Policy Design[/url] anbieten?[/quote]
Das wäre eine Möglichkeit, neben Spezialisierung, was letztendlich nur eine andere Anordnung des Quelltextes darstellt.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten