Сбой, потому что шаблон не подавляет неявное объявление конструктора копирования. Он будет служить простым конструктором преобразования, который можно использовать для копирования объекта, когда его выбирает разрешение перегрузки.
Теперь вы, вероятно, скопировали свою матрицу куда-нибудь, в которой использовался бы неявно определенный конструктор копирования, который делает плоскую копию. Затем скопированная матрица и копия в своем деструкторе удалят один и тот же указатель.
Кроме того, почему требуется чрезвычайно подробный template <typename T> template <typename U>
синтаксис
Потому что задействованы два шаблона: матрица, которая является шаблоном класса, и шаблон конструктора преобразования. Каждый шаблон заслуживает отдельного предложения шаблона со своими параметрами.
Кстати, вы должны избавиться от <T>
в первой строке. Такая вещь не появляется при определении шаблона.
Это плохое решение, так как оно приводит к массовому дублированию кода конструктора копирования
Вы можете определить шаблон функции-члена, который будет выполнять работу, и делегировать как конструктор преобразования, так и конструктор копирования. Таким образом, код не дублируется.
Ричард высказал хорошее замечание в комментариях, которые заставили меня изменить свой ответ. Если функция-кандидат, сгенерированная из шаблона, лучше соответствует неявно объявленному конструктору копирования, тогда шаблон «выигрывает», и он будет вызван. Вот два распространенных примера:
struct A {
template<typename T>
A(T&) { std::cout << "A(T&)"; }
A() { }
};
int main() {
A a;
A b(a); // template wins:
// A<A>(A&) -- specialization
// A(A const&); -- implicit copy constructor
// (prefer less qualification)
A const a1;
A b1(a1); // implicit copy constructor wins:
// A(A const&) -- specialization
// A(A const&) -- implicit copy constructor
// (prefer non-template)
}
Конструктор копирования также может иметь параметр неконстантной ссылки, если любой из его членов имеет
struct B { B(B&) { } B() { } };
struct A {
template<typename T>
A(T&) { std::cout << "A(T&)"; }
A() { }
B b;
};
int main() {
A a;
A b(a); // implicit copy constructor wins:
// A<A>(A&) -- specialization
// A(A&); -- implicit copy constructor
// (prefer non-template)
A const a1;
A b1(a1); // template wins:
// A(A const&) -- specialization
// (implicit copy constructor not viable)
}