Why conversion function is not used for an object when it is assigned to?

1.2k views Asked by At

I learned that we could provide conversion operators for our classes in C++. So I expected that for the following program, c=1; would've used the conversion operator int(). But to my surprise; that doesn't happen and we get a compiler error saying that

error: no match for 'operator=' (operand types are 'C' and 'int').

So I want to know why isn't the conversion operator used here.

struct C {
    explicit C(int);
    operator int&(); 
};

int main() {
    C c({});
    c = 1;   //this gives error. Why the conversion operator int&() is not used here?
}

Note that I know that I can solve the error if I just remove the explicit keyword from the constructor. But my question is about why the conversion operator is not used.

I thought that since we have a conversion operator for our class, the class object can be converted to an int so that it can be assigned to.

2

There are 2 answers

2
user12002570 On

I thought that since we have a conversion operator for our class, the class object can be converted to an int so that it can be assigned to.

Because the user-defined conversions are not considered for the left hand operand of built-in assignment operator. This can be seen from Operators in expression's documentation:

For the built-in assignment operators, conversions of the left operand are restricted as follows:

  • no temporaries are introduced to hold the left operand, and
  • no user-defined conversions are applied to the left operand to achieve a type match with the left-most parameter of a built-in candidate.

(emphasis mine)

This means that the program is ill-formed.

0
Karen Baghdasaryan On

For the formal explanation refer to this answer. I'll try to provide an intuition for why this does not work the way you expected. In your question, you try to work out the following expression

c = 1;

where c is an instance of class C. We can make two ways of working this out.

  • Making an assignment operator accepting argument of type int
  • Making an implicit constructor accepting int.

So if we work with the expression mentioned, above should be sufficient.

However, one might want to write something like this.

int i = c; // again, c is instance of C

We also (if we try to think how a language designer might have thought) need to work this out. So the designers for this purpose decided to make a conversion operator which is especially for cases like this.

In summary

  • If we want to make A from B, we define a constructor of A which accepts B
  • If we also want to get B from A(and we can't or don't want to define a constructor of B which accepts A), we make a conversion operator which converts A to B as we wish.