Making overloaded binary operators commutative

I'm building a class to handle matrix operations that can be used to do linear algebra. I'm just wondering if the following is the best way to overload the scaler multiplication operator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Matrix& operator*(const Matrix::value &vl_scaler, const Matrix &source_obj)
{
    Matrix *mt_build = new Matrix(source_obj);

    size_t loop_run = mt_build->rwDm_rows * mt_build->clDm_columns;

    for(size_t vdDm_iii = 0; vdDm_iii != loop_run; ++vdDm_iii)
    {
        mt_build->vl_strg_array[ vdDm_iii ] *= vl_scaler;
    }

    return *mt_build;
}

Matrix& operator*(const Matrix &source_obj, const Matrix::value &vl_scaler)
{
    return vl_scaler * source_obj;
}


At first I had this as a member function but I couldn't think of how I would make it commutative that way. As a friend function like above I have to define two functions to make it commutative.
Matrix multiplication is not commutative.

[edit]
Oops! The multiplication by a scalar is...

Binary operators should not return a reference, but a new object.

The function that takes the const Matrix& as first argument can be either a member or a non-member function (your choice).

The function that takes the scalar value as first argument must be a non-member function:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Matrix
{
  public:
    Matrix operator*(const value &v1_scaler)
    {
    ...
    }
};

Matrix operator*(const Matrix::value &v1_scaler, const Matrix &source_obj)
{
  return source_obj * v1_scaler;
}

If your class is templated, you will need to add the template boilerplate before the non-member function:

1
2
3
4
5
template <typename ValueT>
Matrix<ValueT> operator*(const Matrix<ValueT>::value &v1_scaler, const Matrix<ValueT> &source_obj)
{
  return source_obj * v1_scaler;
}


BTW, the word "scalar" is spelt "scalar", not "scaler".

Hope this helps.
Last edited on
But matrix multiplication by a scalar is, though you usually see the scalar on the left on paper.
Sorry shacktar, I noticed my mistake while you were typing your response...
I noticed that :)

I was also editing my response to add about the returning the reference and the fact that the operation with the scalar on the left must be a non-member function, but I hit refresh and saw that you had already gotten to that.

Also, alhypo, there's a memory leak in your implementation. You should just create a Matrix as usual (non-dynamically).
Duoas: BTW, the word "scalar" is spelt "scalar", not "scaler".


Oh, man... that's embarrassing. Uhm... my only defense is that it's been 5 years since I was in linear algebra. My browser even told me it was misspelled but I guess I ignored it.

But yeah, Duoas, that makes sense to me now. In my reference material they only ever defined one operator function but it still behaved like it was commutative. Now I realize that it only appeared to be commutative because the the operands were of the same type. I should have thought it through a bit more.

Although I hadn't thought of defining one function as member and the other as a friend so it's good to see how that's done. Thanks.

I'm a few chapters off from templates so that other stuff will probably make sense to me later.

shacktar: ...though you usually see the scalar on the left on paper.


I thought about that as well, but then I wondered what would happen if I wrote an assignment like this:

C = A * c * B

If I had only defined the scalar to operate before the matrix it seems like the compiler would say this is in error because it would try to do A * c first. I guess it depends on whether it works the expression from right to left or left to right. Does anyone happen to know which direction it works?

Thanks for catching that memory leak!
Multiplication is always left-associative. a*b*c == (a*b)*c.
Topic archived. No new replies allowed.