Member functions are matched by their left-hand-side argument which is the this-pointer. Since native types can't have member functions, you have to add right-multiplication with user-defined types through non-member functions (and also for other types you don't 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 the above non-member operator*
implemented in terms of a member operator*=
. It is recommended to write all multiplications as non-member functions, and use a member operator*=
to implement these multiplications with a lhs Matrix element.
This will a) keep the class interface minimal, and b) prevent hidden conversions. E.g. you could have a Matrix class that is implicitly convertible to scalar if the dimensions are 1x1, and these conversions could silently happen if you don't provide a separate overload that 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 on how the lhs Matrix is a copy and not a reference. This allows the compiler to make optimizations such as copy elision / move semantics. Also note that the return type of these operators is Matrix<T>
and not const Matrix<T>
which was recommended in some old C++ books, but which prevents move 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;
}