As some of my code required implicit conversion between matrices of different types (e.g. Matrix<int>
to Matrix<double>
), I defined a templated copy constructor Matrix<T>::Matrix(Matrix<U> const&)
instead of the standard Matrix<T>::Matrix(Matrix<T> const&)
:
template <typename T> class Matrix {
public:
// ...
template <typename U> Matrix(Matrix<U> const&);
// ...
private
unsigned int m_rows, m_cols;
T *m_data;
// ...
};
With an appropriate typecast added to the copy-constructor, this method flawlessly converted between matrices of different types. Surprisingly, it fails with a malloc error in the very situation where a simple copy-constructor would function: where U == T
. Sure enough, overloading the copy-constructor with the default Matrix<T>::Matrix(Matrix<T> const&)
signature solves the problem.
This is a poor solution, as it results in the wholesale duplication of the copy-constructor code (Literally an unchanged copy-and-paste). More importantly, I do not understand why there is a double-free malloc
error without the duplicate code. Furthermore, why is the extremely verbose template <typename T> template <typename U>
syntax required here as opposed to the standard, and much more succinct, template <typename T, typename U>
?
Full source of the templated method, compiled using G++ v4.0.1 on 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));
}
}
}