3

I got this code:

1 #include <iostream>
2 using namespace std;
3
4 class B {
5 private:
6      int n;
7 public:
8      B(int x) : n(x) {}
9      B operator +(B& b) {
10         return B(n+b.n);
11     }
12     friend ostream& operator <<(ostream &out, const B& b) {
13         out << "B: " << b.n;
14         return out;
15     }
16     bool operator <(const B& rhs) const{
17         return n < rhs.n;
18     }
19 };
20
21 B smaller (const B& b1, const B& b2) {
22     if(b1 < b2)
23         return b1;
24     else
25         return b2;
26 }
27
28 int main() {
29     B b1(1), b2(2), b3(3);
30     const B b4 = b1 + (b2 + b3);
31     cout << smaller(b1,b2) << endl;
32     return 0;
33 }

I was asked to point out the errors (explain them) and supply a fix, after finding two and fixing them I got the above code.

When trying to compile it on Visual Code I noticed that line 30 is giving out an error without me understanding why. The error I got was :

no match for 'operator+' (operand types are 'B' and 'B')

and

cannot bind non-const lvalue reference of type 'B&' to an rvalue of type 'B'

After searching on google and finding nothing I tried varius things including adding a const to the parameter in line 9 (operator +) which fixed the problem. I still dont understand what was the problem and I would like to get an explanation.

thank you.

1 Answers1

7

The result of (b2 + b3) is a temporary. That is it's an object of type B that is created and destroyed as part of executing the larger expression.

C++ has a rule that you cannot bind a non-const reference to a temporary. But that is exactly what your code was trying to do. Hence the need for const.

Incidentally the correct signature for your overloaded operator is

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

Both the method and the parameter should be const.

Even better would be to make operator+ a non-member

B operator +(const B& a, const B& b) {
    ...
}

Some more reading.

john
  • 85,011
  • 4
  • 57
  • 81
  • Is there a reason why making `operator+` a non-member function is better? – jyl Jun 29 '20 at 16:41
  • 3
    @user Yes, it's so that the compiler treats' the two parameters of operator+ equally. If operator+ is a member then the first paramater will be treated differently to the second parameter, in particular the compiler will not apply any automatic type conversions to the first parameter. – john Jun 29 '20 at 16:43
  • 2
    @user With the above code for example `b + 2` will aways compile with the compiler using the `B(int)` constructor to create a `B` object from 2. But with `operator+` as a member function `2 + b` will not compile because the compiler doesn't apply the type conversion in that case. With `operator+` as a non-member function both cases will compile. – john Jun 29 '20 at 16:45
  • Do you mean that `(b2+23)` is destroyed right after it is made so it can't be passed to the operator? – Idan Musayev Jun 29 '20 at 17:20
  • 1
    @IdanMusayev No, it's passed to operator OK, I think it's destroyed at the end of the statement (but don't quote me on that). The problem is just this rule about non-const references and temporaries. Why that rule exists is another question, I'm not sure I could give a good answer to that. – john Jun 29 '20 at 17:39