Advertisement

overloaded friend operator= with templates - compiler errors

Started by August 03, 2002 12:04 PM
10 comments, last by cheeZe gOd 22 years, 4 months ago
Thanks all who are reading this! Guess I'll just post the code in question.
      
template <class theClass>
class ctBag
{
public:
	theClass* operator[](unsigned int index);
	theClass& operator= (theClass info);
	theClass& operator= (theClass* info);
        friend theClass& operator= (theClass leftValue, theClass rightValue); //this is the problem code

};

template <class theClass>
theClass& operator= (theClass leftValue, theClass rightValue)
{
	;
}
    

//For errors I get:

error C2801: 'operator =' must be a <Unknown> member
//3 times and

error C2954: template definitions cannot nest
  
for the next template after the operator= in question. I know it's just a syntax error, but still can't figure it out. I read the Wrox Press C++ tutorial that came with my VC++ about this throughly with no avail. The MSDN library on the errors didn't help (or I didn't properly understand them). I also tried making it into a normal (non-friend) function
   
template <class theClass>
class ctBag
{
public:
	theClass* operator[](unsigned int index);
	theClass& operator= (theClass info);
	theClass& operator= (theClass* info);
        friend theClass& operator= (theClass leftValue, theClass rightValue); //this is the problem code

};

template <class theClass>
theClass& operator= (theClass leftValue, theClass rightValue);
    
and got a C2801's and two C2954's. I seem to be having alot of template problems (working on reusable ADT classes with inheritance) so if someone could give me a refrence to a good web page/ebook/paper book with this kind of stuff it would be helpful (every beginer's c++ book has templates, overloaded operator= and friend functions, but a friend overloaded operator= in a template is a different story Thanks again! cheeZe gOd [edited by - cheeze god on August 3, 2002 1:36:43 PM] [edited by - cheeze god on August 3, 2002 5:53:58 PM]
cheeZe gOd
quote:
error C2801: ''operator ='' must be a member


As the error message implies, overloaded operator = must be a member function. A friend is not a member function. Besides, even if operator = could be a friend function, you''re code would still croak:
ctBag a;
ctBag b;
// explodes here
b = a; // ambiguous, b.operator =(a) or operator =(a, b)?
Advertisement
Thanks fallenang3l!

(Oh, and note that the real compiler error came out wrong in HTML because of the pointed brackets, in source brackets it shows up properly.)

Your responce has to do with how I got to needing a friend operator= in the first place (which I didn''t mention in my first post).

Testing my operator=''s I found that


  ctBag<int> bag;ctBag<int> bag2(20, 10); //new bag with 20 items, all set to 10bag = bag2;  


produced a memory error, and pinned the cause down to the
theClass& operator= (theClass info);
theClass& operator= (theClass* info);
functions not being called at all. A default copy constructor was used, it seems. This does a shallow, not a deep copy and causing a nice DEBUG ASSERTION FAILED.

Going back into the Wrox Press ebook mentioned before it reminded me of one nuance of the language, that "a member operator function always provides the left argument as the pointer this." This (forgive the pun) is why I wanted a friend operator= to begin with.

So
ctBag a;
ctBag b;
a = b; //not ambiguous since both arn''t pointers, calls operator=(a, b)

and

ctBag* a;
ctBag* b = new ctBag();
a = b; //calls operator=(b)

So...can we only do =''s with pointers? If so, I can just move on and live with it.

Thanks again!

A confuzed,

cheeZe gOd
cheeZe gOd
cheeZe gOd, I''m afraid you''re utterly confused. First of all, operator = MUST be a member function. A friend function is NOT a member function. It''s a C++ syntax rule. Second, the correct syntax for operator = is:
class_name & operator =(const class_name & obj);
quote:
ctBag a;
ctBag b;
a = b; //not ambiguous since both arn''t pointers, calls operator=(a, b)


What are you talking about? This WILL call operator = and NOT the copy constructor. The reason why it calls the copy ctor in your case is that you''re passing by value to operator =, and that causes a temp object to be created by the copy ctor. To fix this problem, use the proper syntax for operator =.
Why yes, I am utterly confused.

Thanks for the help again!

Ok, so what you're saying is that

ctBag a;
ctBag b;
a = b;

is incorrect syntax in the first place because I should be passing by refrence and not by value for operator=. Right?

As is it calls the copy constructor? I'll make sure that's getting called then (away from compiler right now).

A less confused

cheeZe gOd

[edited by - cheeze god on August 4, 2002 12:30:38 PM]
cheeZe gOd
No no no no. This is correct syntax:

ctBag a;
ctBag b;
a = b;

The problem is with your equals operator function. It should be:

theClass& operator= (theClass & tc)

This way you are passing and returning references and are not using friends. The LEFT VALUE is the invoking object and the RIGHT VALUE is the passed reference.
Advertisement
Thanks Anonymous!

But I'm still having problems.

Ok, I found that that works A-OK with all of my non-templated classes (like my ctString).


  ctString string;ctString string2("Bob");cout<<string2<<endl;string = string2;cout<<string<<endl;//will call operator= and produce Bob twice, as expected.//ButctBag<int> bag;ctBag<int> bag2(10, 20);bag = bag2;  


with almost identical operator= functions...produces a memory error and never calls operator=.

Works fine with non-templated, with templates, all hell brakes loose. I can't figure out why, any suggestions?

Thanks for all the help!

A confuzed and at wit's end,

cheeZe gOd

[edited by - cheeze god on August 7, 2002 4:35:57 PM]
cheeZe gOd
You haven''t told us how you''ve implemented operator= for ctBag. The signature looks wrong, probably should be something like:

  template <class theClass>class ctBag{public:	ctBag<theClass>& operator= (const theClass& rhs);};  

Note the return type. If you return a different class, chaining of operator= calls will have surprising effects.

Is it only operator= that is parameterised by type? If so, it should look more like:

  class ctBag{public:	template <class theClass>	ctBag<theClass>& operator= (const theClass& rhs);};  
Another point: under certain conditions, a statement that looks like it should call the (overloaded) assignment operator actually ends up calling the copy constructor. For instance,
MyClass a;MyClass b = a; 

will actually call Myclass::MyClass(const MyClass &).

Never implement the assignment operator without also implementing the copy constructor, and vice versa.



Don''t listen to me. I''ve had too much coffee.
quote: Original post by Sneftel
Another point: under certain conditions, a statement that looks like it should call the (overloaded) assignment operator actually ends up calling the copy constructor. For instance,
MyClass a;MyClass b = a;  

will actually call Myclass::MyClass(const MyClass &).

Never implement the assignment operator without also implementing the copy constructor, and vice versa.



Don''t listen to me. I''ve had too much coffee.


Not true. This will undoubtedly call b''s copy ctor, but an implementation can decide to let the default copy ctor pass the task of memberwise copying to the assignment operator =. Ex:
Myclass::MyClass(const MyClass & rhs)
{
*this = rhs;
}
or the implementation may do the copy in the copy ctor (like you said).

This topic is closed to new replies.

Advertisement