Wie einige von meinem Code implizite Konvertierung zwischen Matrizen verschiedenen Typen erforderlich (zB Matrix<int>
zu Matrix<double>
), definierte ich einen Templat-Copykonstruktor Matrix<T>::Matrix(Matrix<U> const&)
statt den Standard Matrix<T>::Matrix(Matrix<T> const&)
:Templated Kopie-Konstruktor nicht mit spezifischem Templat-Typ
template <typename T> class Matrix {
public:
// ...
template <typename U> Matrix(Matrix<U> const&);
// ...
private
unsigned int m_rows, m_cols;
T *m_data;
// ...
};
Mit einer geeigneten Typumwandlung, die dem Kopierkonstruktor hinzugefügt wurde, wurde diese Methode fehlerfrei zwischen Matrizen unterschiedlicher Typen konvertiert. Überraschenderweise schlägt es mit einem malloc-Fehler in der Situation fehl, in der ein einfacher Kopierkonstruktor funktionieren würde: where U == T
. Sicher, das Überladen des Kopierkonstruktors mit der Standard-Signatur Matrix<T>::Matrix(Matrix<T> const&)
löst das Problem.
Dies ist eine schlechte Lösung, da es zu einer doppelten Kopie des Kopierkonstruktorcodes kommt (wörtlich ein unverändertes Kopieren und Einfügen). Noch wichtiger, ich verstehe nicht, warum es einen doppelten malloc
Fehler ohne den doppelten Code gibt. Außerdem, warum ist die extrem ausführliche template <typename T> template <typename U>
Syntax erforderlich hier im Gegensatz zum Standard, und viel prägnanter, template <typename T, typename U>
?
Vollständige Quelle der Vorlagenmethode, kompiliert mit G ++ v4.0.1 unter Mac OS 10.5.
template <typename T> template <typename U> Matrix<T>::Matrix(Matrix<U> const& obj) {
m_rows = obj.GetNumRows();
m_cols = obj.GetNumCols();
m_data = new T[m_rows * m_cols];
for (unsigned int r = 0; r < m_rows; ++r) {
for (unsigned int c = 0; c < m_cols; ++c) {
m_data[m_rows * r + c] = static_cast<T>(obj(r, c));
}
}
}
Ihre Erklärung für den Malloc-Fehler klingt vor Ort. Gibt es einen bestimmten Grund dafür, warum Compiler keine Vorlagenelementfunktion als Kopierkonstruktor verwenden können? Danke für die Information und für den Hinweis zur Vermeidung von Code-Duplikation. –
Wenn Sie diese Vorlage haben, ist dies noch keine Funktion. Nur die Verwendung mit einem Template-Argument erzeugt eine (member-) Funktion daraus (Spezialisierung genannt). Dies ist auch der Grund, warum Mitgliedervorlagen nicht virtuell sein können: Sie wissen nicht im Voraus, welche Funktionen daraus generiert werden. –
Das macht sehr viel Sinn - das funktioniert nicht gerade deshalb, weil man Vorlagenparameter deklarieren oder die vollständige Quelle der Implementierung einbeziehen muss. Danke noch einmal. –