It fails because a template doesn't suppress the implicit declaration of a copy constructor. It will serve as a simple converting constructor, which can be used to copy an object when overload resolution selects it.
Now, you probably copied your matrix somewhere, which would use the implicitly defined copy constructor which does a flat copy. Then, the copied matrix and the copy would both in their destructor delete the same pointer.
Furthermore, why is the extremely verbose template <typename T> template <typename U>
syntax required
Because there are two templates involved: The Matrix, which is a class template, and the converting constructor template. Each template deserves its own template clause with its own parameters.
You should get rid of the <T>
in your first line, by the way. Such a thing does not appear when defining a template.
This is a poor solution, as it results in the wholesale duplication of the copy-constructor code
You can define a member function template, which will do the work, and delegate from both the converting constructor and the copy constructor. That way, the code is not duplicated.
Richard made a good point in the comments which made me amend my answer. If the candidate function generated from the template is a better match than the implicitly declared copy constructor, then the template "wins", and it will be called. Here are two common examples:
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)
}
A copy constructor can have a non-const reference parameter too, if any of its members has
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)
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…