Поскольку часть моего кода требовала неявного преобразования между матрицами разных типов (например, Matrix<int>
в Matrix<double>
), я определил шаблонный конструктор копирования Matrix<T>::Matrix(Matrix<U> const&)
вместо стандартного 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;
// ...
};
При добавлении в конструктор копирования соответствующего приведения типов этот метод безупречно преобразовывался между матрицами разных типов. Удивительно, но он падает с ошибкой malloc в той самой ситуации, когда функционировал бы простой конструктор копирования: где U == T
. Разумеется, перегрузка конструктора копирования сигнатурой по умолчанию Matrix<T>::Matrix(Matrix<T> const&)
решает проблему.
Это плохое решение, так как оно приводит к массовому дублированию кода конструктора копирования (буквально неизменное копирование и вставка). Что еще более важно, я не понимаю, почему возникает ошибка double-free malloc
без повторяющегося кода. Кроме того, почему здесь требуется чрезвычайно подробный синтаксис template <typename T> template <typename U>
в отличие от стандартного и гораздо более лаконичного template <typename T, typename U>
?
Полный исходный код шаблонного метода, скомпилированный с использованием G++ v4.0.1 в 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));
}
}
}