"no match for 'operator='", even if it is there

Nov 14, 2012 at 1:30pm
Dear all,
I have a strange problem that I don't figure out.
myclass is the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class myclass{
public:
	myclass();
	~myclass();
	double & operator[](unsigned int);
	myclass & operator=(myclass &);
	myclass operator+(myclass &);
private:
	double fPrivate[3];
};

myclass::myclass(){
	for(unsigned int ii = 0; ii < 3; ii++){
		fPrivate[ii] = 0.;
	}
}

myclass::~myclass(){
}

double & myclass::operator[](unsigned int ii){
	if(ii < 3) return fPrivate[ii];
}

myclass & myclass::operator=(myclass & right){
	for(unsigned int ii = 0; ii < 3; ii++){
		fPrivate[ii] = right[ii];
	}
	return *this;
}

myclass myclass::operator+(myclass & right){
	myclass result;
	for(unsigned int ii = 0; ii < 3; ii++){
		result[ii] = fPrivate[ii] + right[ii];
	}
	return *this;
}

and this is the main:
1
2
3
4
5
6
int main(){
	myclass a, b;
	myclass c = a + b;
	cout << c[1] << endl;
	return 0;
}

This compiles and runs without problems.
When I change the main into
1
2
3
4
5
6
7
int main(){
	myclass a, b;
	myclass c;
	c = a + b;
	cout << c[1] << endl;
	return 0;
}

I get the following error message

error: no match for 'operator=' in 'c = myclass::operator+(myclass&)(((myclass&)(& b)))'

Isn't this strange?
What is the difference between the two main codes?
I don't get the error message.
Thanks in advance.

Fil
Nov 14, 2012 at 1:45pm
operator= needs to take the argument either by value or by reference to const.

The following works for me:

1
2
3
4
myclass & myclass::operator=(myclass right) {
    std::swap(fPrivate, right.fPrivate);
    return *this;
}


Oh, and yes, the difference is that the second code attempts assignment, while the first does not (the equals sign doesn't always mean assignment, just like the asterisk doesn't always mean multiplication)
Last edited on Nov 14, 2012 at 1:50pm
Nov 14, 2012 at 2:07pm
First of all executing of expression a + b results in creating unnamed temporary object. Temporary objects can be binded only with const reference (if of course you are not using the language extensions of MS VC++) .
In the code snip below

1
2
3
4
5
6
int main(){
	myclass a, b;
	myclass c = a + b;
	cout << c[1] << endl;
	return 0;
}


in the statement

myclass c = a + b;

object c is being created. So in this case a copy constructor is used. You did not define a copy constructor yourself so the compiler created implicit copy constructor of type

myclass( const myclass & );

Because this implicit copy constructor has const reference as the parameter it can accept a temporary unnamed object.

Now consider the second code snip

1
2
3
4
5
6
7
int main(){
	myclass a, b;
	myclass c;
	c = a + b;
	cout << c[1] << endl;
	return 0;
}


Here object c was created in statement

myclass c;

by using the default constructor. So in statement

c = a + b;

the copy assignment operator will be used instead of the copy constructor. You defined it such a way that it takes non-const reference to an object of the class. But non-const reference can not be binded with a temporary unnamed object. So the compiler issues the error.

Though your copy assignment operator is correct it is better to define it with const reference as the parameter. In this case you can use it with temporary unnamed objects or const objects in the right side of the assignment operator.
Last edited on Nov 14, 2012 at 2:12pm
Nov 14, 2012 at 3:15pm
Crystal clear, thanks to all!
Nov 14, 2012 at 3:17pm
Just in case you are running into another missbehavior soon: probably you want to return result rather than *this from +
Nov 14, 2012 at 4:51pm
zombie, thanks.
copy paste problem
Topic archived. No new replies allowed.