Multiplication of an object with a constant on the left

I have a Matrix class and it overloads the * operators for scalar and matrix multiplications.

 template <class T> class Matrix { public: // ... Matrix operator*(T scalar) const; // ... } // ... template <class T> Matrix<T> Matrix<T>::operator*(T RightScalar) const { Matrix<T> ResultMatrix(m_unRowSize, m_unColSize); for (uint64_t i=0; i<m_unRowSize; i++) { for (uint64_t j=0; j<m_unColSize; j++) { ResultMatrix(i, j) = TheMatrix[m_unColSize * i + j] * RightScalar; } } return ResultMatrix; } // ... 

I can multiply the matrix object with a scalar on the right side without any problems:

 Matrix<double> X(3, 3, /* ... */); // Define a 3x3 matrix and initialize its contents Matrix<double> Y; // Define an output matrix Y = X * 10.0; // Do the linear operation 

But how can I multiply it on the left side in the same way?

 Matrix<double> X(3, 3, /* ... */); Matrix<double> Y; Y = 10.0 * X; 

In arithmetic, this is a general notation for writing constants on the left side when performing multiplication. I would like to obey this rule to make my code more readable.

Is it possible to implement this in C ++?
If possible, how can I change the class method in my code?

+8
c ++ operator-overloading templates member-functions
source share
2 answers

Member functions are matched by their left argument, which is this pointer. Since native types cannot have member functions, you need to add the correct multiplication with custom types through functions other than members (as well as for other types that you do not have write access to).

 template<typename T> Matrix<T> operator*(T const& scalar, Matrix<T> rhs) { // scalar multiplication is commutative: s M = M s return rhs *= scalar; // calls rhs.operator*=(scalar); } 

NOTE : I wrote above the non-member operator* , implemented in terms of the member operator*= . It is recommended that you write all the multiplications as non-member functions, and use the operator*= element to implement these multiplications using the Lhs matrix element.

This will: a) maintain a minimal class interface and b) prevent hidden conversions. For example. you can have a Matrix class that is implicitly converted to scalar if the sizes are 1x1, and these conversions can happen unexpectedly if you do not provide a separate overload, which is a direct match.

 template<typename T> Matrix<T> operator*(Matrix<T> lhs, T const& scalar) { return lhs *= scalar; // calls lhs.operator*=(scalar); } template<typename T> Matrix<T> operator*(Matrix<T> lhs, Matrix<T> const& rhs) { return lhs *= rhs; // calls lhs.operator*=(rhs); } 

Notice how the lhs matrix is ​​a copy, not a link. This allows the compiler to do optimizations such as copy / elite semantics. Also note that the return type of these operators is Matrix<T> , not const Matrix<T> , which was recommended in some old C ++ books, but which prevents movement semantics in C ++ 11.

 // class member template<typename T> Matrix<T>& Matrix<T>::operator*=(Matrix<T> const& rhs) { // your implementation return *this; } // class member template<typename T> Matrix<T>& Matrix<T>::operator*=(T const& scalar) { // your implementation return *this; } 
+9
source share

For this you need a non-member function:

 template <typename T> Matrix<T> operator*(T scalar, Matrix<T> const & matrix) { return matrix * scalar; } 

Overloads of non-member operators allow you to specify any type on both sides, while overloads of elements always get the object on the left.

+8
source share

All Articles