0

I have a following code which is below.

When I write o1 = o2, void operator=(TestClass& _rhs) is called. It's ok.

But when I do o1 = test_function();, first operator float() is called, then void operator=(float _value). It's logically correct, but why is void operator=(TestClass& _rhs) not invoked?

class TestClass
{
public:
    TestClass(float _value)
    {
        value = _value;
    }

    operator float()
    {
        return value;
    }

    void operator=(float _value)
    {
    }

    void operator=(TestClass& _rhs)
    {
    }

private:
    float value;
};

TestClass test_function()
{
    TestClass result = 0;
    return result;
}

int main()
{
    std::cout << "Hello World!\n"; 

    TestClass o1(1), o2(1);

    o1 = o2;

    o1 = test_function();
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
zulunation
  • 297
  • 1
  • 5
  • 13
  • Looks like copy elision to me. – mrks Mar 14 '21 at 19:52
  • 1
    Does this answer your question? [What are copy elision and return value optimization?](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization) – mrks Mar 14 '21 at 19:53
  • You're overcomplicating this: `void foo(int& i); foo(get_int());` – chris Mar 14 '21 at 19:54
  • Try making assignment operator argument const? `void operator=(const TestClass& rhs)` – Hitobat Mar 14 '21 at 19:59

2 Answers2

2

why void operator=(TestClass& _rhs) is not involved?

Because that assignment operator is malformed. It should be:

void operator=(TestClass const& _rhs)
//                CONST! ^^^^^

Your form, void operator=(TestClass& _rhs) will not accept prvalues (temporaries), like the temporary returned from test_function().

So, the only valid assignment in your code is void operator=(float _value), which is possible because your class can implicitly convert to a float.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
1

You should declare operator= differently for TestClass. Either use

void operator=(const TestClass& _rhs)

or

void operator=(TestClass _rhs)

This is because function test_functions returns a temporary value, and you cannot bind temporarily to a non-const lvalue reference. This is why the other operator=(float) is selected.

You may find overload resolution rules here: https://riptutorial.com/cplusplus/example/8117/steps-of-overload-resolution

mnikolic
  • 572
  • 1
  • 5
  • 9