I'm not sure that I have understood your issue correctly, but your interface actually does not define the copy assignment operator (nor the copy constructor), because the "template copy op=" is not a true copy op= (and the "template copy ctor" is not a true copy ctor).
Here's a simple example to show the problem:
#include <cstdio>
using std::puts;
struct M {
M& operator=(M const&) {
puts("M::operator=(M const&)");
return *this;
}
};
template<typename T> class Foo {
M m;
template<typename U> friend class Foo; // (needed for m = rhs.m; below)
public:
template<typename U> Foo& operator=(Foo<U> const& rhs) {
puts("[template] Foo<T>::operator=(Foo<U> const&)");
m = rhs.m; // calls M's op=
return *this;
}
};
int main() {
puts("===");
Foo<int> a;
Foo<double> b;
a = b;
puts("---");
Foo<int> c;
Foo<int> d;
c = d;
puts("===");
}
That prints:
===
[template] Foo<T>::operator=(Foo<U> const&)
M::operator=(M const&)
---
M::operator=(M const&)
===
Why is there only one line for the second assignment? That's because c = d;
calls Foo<int>::operator=(Foo<int> const&)
i.e. the true copy assignment operator, and since we have not declared it (only a template version) the compiler generates it automatically (which does a member-wise assignment, hence the call to M::operator=
).
Thus, me must add it explicitly to the class:
// ...
Foo& operator=(Foo const& other) {
puts("[non-template] Foo<T>::operator=(Foo<T> const&)");
m = other.m;
return *this;
}
};
and then it prints:
===
[template] Foo<T>::operator=(Foo<U> const&)
M::operator=(M const&)
---
[non-template] Foo<T>::operator=(Foo<T> const&)
M::operator=(M const&)
===
So, in your example, p = foo();
does not invoke your user-defined template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs)
but the implicitly-generated version that simply assigns the pointee
member (without releasing the source).