=================== Template-Funktionen =================== Bislang war `init` eine Methode innerhalb der Matrix-Klasse: ---- CODE (type=cpp) ---------------------------------------------------------- void init() { for (std::size_t i = 0; i < m; ++i) { for (std::size_t j = 0; j < n; ++j) { data[i*incRow + j*incCol] = j * n + i + 1; } } } ------------------------------------------------------------------------------- Da stellt sich jedoch die Frage, ob so eine Methode innerhalb der Matrix-Klasse sinnvoll ist. Es ist erstrebenswert, Klassen so zu entwerfen, dass * sie minimalistisch sind, d.h. möglichst wenig Ballast mitführen und andererseits * sie genügend umfangreich sind, so dass mögliche Nutzungen nicht eingeschränkt werden. Da die Klasse bereits Zugriffsmethoden für den Zugriff auf ein einzelnes Element anbietet, kann die `init`-Methode aus der Klasse herausgelöst werden. Das hätte auch den Vorteil, dass die Abbildung von Indizes in eine Speicherzelle nur in den entsprechenden Zugriffsmethoden stattfinden würden. Wenn `Matrix` keine Template-Klasse wäre, könnte das so aussehen: ---- CODE (type=cpp) ---------------------------------------------------------- void init_matrix(Matrix& A) { for (std::size_t i = 0; i < A.m; ++i) { for (std::size_t j = 0; j < A.n; ++j) { A(i, j) = j * A.n + i + 1; } } } int main() { Matrix A(7, 8, StorageOrder::ColMajor); init_matrix(A); std::printf("A =\n"); A.print(); } ------------------------------------------------------------------------------- In C++ sind Template-Deklarationen auch für Funktionen denkbar. Wir könnten die Funktion entsprechend mit dem Elementtyp der Matrix parametrisieren: ---- CODE (type=cpp) ---------------------------------------------------------- template void init_matrix(Matrix& A) { for (std::size_t i = 0; i < A.m; ++i) { for (std::size_t j = 0; j < A.n; ++j) { A(i, j) = j * A.n + i + 1; } } } int main() { Matrix A(7, 8, StorageOrder::ColMajor); init_matrix(A); std::printf("A =\n"); A.print(); } ------------------------------------------------------------------------------- Bei genauerer Betrachtung lässt sich feststellen, dass die Typinformation beim Aufruf von `init_matrix` redundant ist. Da A den Typ `Matrix` hat und `init_matrix` einen Parameter des Typs `Matrix&` erwartet, könnte daraus geschlossen werden, dass für `T` bei diesem Aufruf `double` einzusetzen ist. Freundlicherweise kommt C++ uns hier entgegen, d.h. wenn bei einem Aufruf einer Template-Funktion die Template-Parameter sich aus den Datentypen der aktuellen Parameter ableiten lassen, dann kann die explizite Angabe von Template-Parametern wegfallen: ---- CODE (type=cpp) ---------------------------------------------------------- template void init_matrix(Matrix& A) { for (std::size_t i = 0; i < A.m; ++i) { for (std::size_t j = 0; j < A.n; ++j) { A(i, j) = j * A.n + i + 1; } } } int main() { Matrix A(7, 8, StorageOrder::ColMajor); init_matrix(A); std::printf("A =\n"); A.print(); } ------------------------------------------------------------------------------- Aufgabe ======= Entfernen Sie analog dazu die `print`-Methode aus der Matrix-Klasse und wandeln Sie sie in eine Template-Funktion um. Vorlage ======= :import: session9/matrix_class10.cpp :navigate: up -> doc:index back -> doc:session9/page02 next -> doc:session9/page04