1

Why the following code doesn't compile:

B b1(1), b2(2), b3(3);
const B b4 = b1 + (b2 + b3);

Until I replace this:

B operator+(B& b) {
    return B(n + b.n);
}

with this:(I don't know why to write const the compiler suggested that)

B operator+(const B& b) {
    return B(n + b.n);
}

Errors I get:

invalid operands to binary expression ('B' and 'B')

note: candidate function not viable: expects an l-value for 1st argument

note: candidate template ignored: could not match 'reverse_iterator' against 'B' operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_iterator<_Iter>& __x)

Plus, why this works? (it's similar to the previous case)

bool Test(int x)
{
    return x==0;
}
Test(0);
JaMiT
  • 14,422
  • 4
  • 15
  • 31

1 Answers1

1
const B b4 = b1 + (b2 + b3);

According to the order of operations, the first subexpression to evaluate is b2 + b3. This invokes B::operator+, which returns a B object. More precisely, a temporary B object is returned, one that will be used to help evaluate this full expressions and then discarded. This is much like making notes on scratch paper as you work through a long calculation by hand.

The next subexpression to evaluate is b1 plus the temporary object. This invokes b1.operator+ with the temporary B object as the argument. When the operator's signature is

B operator+(B& b)

there is a problem because the C++ language states that a non-const reference cannot bind to a temporary object. That is, the reference parameter (B& b) does not match the temporary object. You can solve this by changing the reference from one that is not const-qualified to one that is.

B operator+(const B& b)

This version of the operator takes a const reference, which can bind to a temporary object. (Again, this is simply a rule of the language. You can debate the reasons for it, but the rule still stands.)

Note that this is not a full solution since addition tends to be symmetric. To accommodate the scenario where the left side of the parentheses is const-qualified, *this also needs to be const-qualified.

B operator+(const B& b) const

For more tips, see the basic rules and idioms for operator overloading. You might find that you don't necessarily want operator+ to be a member function.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • Thanks, But (b2 + b3) + b1 worked without adding const for this –  Jun 13 '20 at 01:30
  • `(b2+b3)+b1` works (temporary is `*this`). It is `b4+b1` which fails (`b4` is `const`). – Jarod42 Jun 13 '20 at 01:31
  • @Jarod42 Is that one of the weird things with temporaries? Bah. If you write solid code, you forget the intricacies of how bad the code has to get before it triggers an actual error... – JaMiT Jun 13 '20 at 01:32
  • 1
    @zoorish Sorry, I did not test the code before posting. I often do, but in this case mocking up `B` seemed like too much work. (That is supposed to imply that if you had provided a minimal definition of `B` in the question -- something I could copy -- I would have double-checked by passing the code through a compiler.) – JaMiT Jun 13 '20 at 01:36