Overloading "+=" operator: c+=a_times_b works, but c+=a*b does not?

134 Views Asked by At

I have two classes A and B. The product A*B should be of type B. Since variables of type B will occupy great amounts of memory, I need to avoid operations like B_1 = B_1 + (A_1 * B_2), where (A_1 * B_2) would be temporarily allocated. In other words, I need B_1 += A_1 * B_2.

I have tried this:

struct A {
    int a;
};

struct B {
    double b[size];

    void operator += (pair<A*, B*> & lhsA_times_rhsB){
        A & lhsA = *lhsA_times_rhsB.first;
        B & rhsB = *lhsA_times_rhsB.second;

        b[lhsA.a] += rhsB.b[lhsA.a];
    }
};

inline pair<A*, B*> operator*( A& lhsA,  B& rhsB){
    return make_pair(&lhsA, &rhsB);
};

int main(){
    A A_in;
    B B_in, B_out;

    pair<A*, B*> product = A_in*B_in;

    B_out += product;    //this works!
    B_out += A_in*B_in;  //doesn't work!? (Compiler: "No viable overloaded '+='")

    return 0;
}
  1. Why is B_out += product okay but B_out += A_in * B_in is not?

  2. Is there a better way to implement the +=-operator for this use? Maybe without defining the helper object pair<A*, B*>?

1

There are 1 best solutions below

0
On

The issue is that you're creating a temporary pair<A*, B*> when you multiply A_in*B_in

The signature for your operator+= is

 void operator += (pair<A*, B*> & lhsA_times_rhsB)

You cannot create a non-const reference from a temporary. The compiler* (gcc) tells you as much:

error: cannot bind non-const lvalue reference of type 'std::pair<A*, B*>&' to an rvalue of type 'std::pair<A*, B*>'

How to read the error message:

The 'rvalue' is your temporary pair<A*, B*> returned from operator*, and the 'non-const lvalue reference' is the targeted pair<A*, B*>&

Solution:

Change operator+= to use a const reference instead:

void operator += (const pair<A*, B*>& lhsA_times_rhsB)

You do not appear to need to modify lhsA_times_rhsB, so you should prefer constness.

Demo

*Clang's error message is actually less informative here because it gets broken into two. The first one is "error: no viable overloaded '+='", and the second one is only slightly more descriptive: "candidate function not viable: expects an l-value for 1st argument"