Reputation: 11753
In the following codes, I illustrate an example of operator overloading:
#include <iostream>
using namespace std;
template <typename T>
class A
{
public:
A() {};
A( T &obj) {value = obj;};
~A() {};
T value;
template <typename E>
A<T>& operator = (const A<E> &obj)
{
cout<<"equal operator"<<endl;
if(this == &obj)
return *this;
value = obj.value;
return *this;
}
};
int main()
{
int temp;
temp = 3;
A<int> myobjects(temp);
cout<<myobjects.value<<endl;
temp = 7;
A<int> yourobjects(temp);
yourobjects = myobjects;
cout<<yourobjects.value<<endl;
return 0;
}
However, when I debug this program, I find that the main program does not invoke the equal operator overloading function. However, if I change the equal operator in the following way:
A<T>& operator = (const A<T> &obj)
{
cout<<"equal operator"<<endl;
if(this == &obj)
return *this;
value = obj.value;
return *this;
}
It will work. Do you have any ideas why the initial function does not work?
Upvotes: 2
Views: 718
Reputation: 320481
Your template version of assignment operator does not suppress the generation of compiler-provided non-template copy-assignment operator for your class. The compiler will implictly declare and define a copy-assignment operator with the following signature
A<T>& operator =(const A<T>&);
In the overload resolution process for copy-assignment the compiler-provided version wins (since it is more specialized).
Your template version of assignment operator will only be considered for conversion-assignment. E.g. if at some point you'll want to assign A<int>
object to A<double>
object, your template version of assignment operator will be used. But when you assign A<int>
to A<int>
your operator is ignored since the compiler-declared version is a better match.
When you declare your own version of copy-assignment with
A<T>& operator =(const A<T>&);
signature, it suppresses the compiler-generated one. Your version gets used.
This means that if you want to have your own copy-assignment operator as well as template conversion-assignment operator, you need to explicitly implement both in your class.
P.S. As '@Cheers and hth. - Alf' correctly noted, your template version of assignment operator is not even valid in general case. Pointers this
and &obj
generally have different unrelated types. You are not allowed to compare pointers of different unrelated types.
Upvotes: 7
Reputation: 355069
A copy assignment operator with the signature T& operator=(T const&)
is automatically declared and defined by the compiler if you do not define your own copy assignment operator.
Your assignment operator template is not a copy assignment operator because it is a template (a template is never a copy assignment operator).
In your example, myobjects
and yourobjects
are both of type A<int>
. There are two operator=
overloads the compiler can choose:
A<int>& operator=(A<int> const&)
, which is implicitly provided by the compiler, orA<int>& operator=(A<int> const&)
, a specialization of your template.You'll notice that both of these have exactly the same signature. One of the rules of overload resolution is that all other things being equal, nontemplates are preferable to templates. The implicitly-declared copy assignment operator is not a template, and your overload is a template, so the implicitly-declared operator=
is selected.
To suppress the implicitly-declared copy assignment operator, you need to declare and define your own:
A& operator=(A const&) { /* etc. */ }
Upvotes: 4