How can I overload the multiplication operator? - c++

I have a Matrix class. I am overloading the multiplication operator, but it's working only if I call Matrixscalar; isn't working for scalarMatrix. How can I fix this?
#include <iostream>
#include <stdint.h>
template<class T>
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
Matrix(const Matrix<T>& m);
Matrix();
~Matrix(); // Destructor
Matrix<T> operator *(T k) const;
unsigned rows, cols;
private:
int index;
T* data_;
};
template<class T>
Matrix<T> Matrix<T>::operator *(T k) const {
Matrix<double> tmp(rows, cols);
for (unsigned i = 0; i < rows * cols; i++)
tmp.data_[i] = data_[i] * k;
return tmp;
}
template<class T>
Matrix<T> operator *(T k, const Matrix<T>& B) {
return B * k;
}
Edited
I implemented what chill suggested, but I'm getting the following error:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:44:19: error: no match for ‘operator*’ in ‘12 * u2’
main.cpp:44:19: note: candidate is:
lcomatrix/lcomatrix.hpp:149:11: note: template<class T> Matrix<T> operator*(T, const Matrix<T>&)
make: *** [main.o] Error 1

Don't make the operator a member. Define an operator*= as a member of Matrix, then define two free operator*, using *= in their implementation.

Define an operator* outside the class, which just reverses the arguments. And declare the other operator* as const.
template<typename T> Matrix<T> operator* (T k, const Matrix<T> &m) { return m * k; }

The class member operator * operates on it's corresponding object (to the left), invoking M * scalar corresponds to A.operator*(scalar) - this obviously doesn't apply if you switch the order since you don't have operator * defined for the scalar. You can create a global operator * implementation which accepts scalar as first (left) operand and matrix as the second. Inside the implementation switch the order and invoke your inclass class operator *. E.g.:
template <class T>
Matrix<T> operator *(T scalar, const Matrix<T> &M)
{
return M * scalar;
}

Related

Left-hand operator overloading is ambiguous

I created a Matrix template class to work with matrixes of various types (int, float, 2D-points, etc.)
template<typename Type>
class Matrix {
...
};
I added some operators like +, -, *, /. These functions also need to be templated, because I want to multiply a Matrix type by float , or by a Matrix.
Here is my multiplication implementation:
template<typename T>
Matrix operator*(const T &other) const {
Matrix temp(*this);
temp *= other;
return temp;
}
Matrix &operator*=(const Matrix &other) {
auto temp = Matrix(rows, other.columns);
for (int i = 0; i < rows; i++)
for (int j = 0; j < other.columns; j++) {
temp.matrix[i][j] = Type();
for (int k = 0; k < other.rows; k++)
temp.matrix[i][j] += matrix[i][k] * other.matrix[k][j];
}
AllocMatrixData(temp.rows, temp.columns);
matrix = temp.matrix;
return *this;
}
template<typename T>
Matrix &operator*=(const T value) {
for (ProxyVector<Type> &line : matrix) <- ProxyVector is just a wrapper
line *= value;
return *this;
}
I want my Matrix object to be on the left side, so I can do this:
Matrix * 5
However I can't do this:
5 * Matrix
So I added a function that can take a type T as the first argument and Matrix as second.
template<typename T>
friend Matrix<Type> operator*(const T Value, const Matrix<Type> &other)
{
return other * Value;
}
But now Matrix*Matrix multiplication is ambiguous. I think I understand why - I have two functions that take T and Matrix and in this case T can be the Matrix type too. So how do I fix this?
When multiplying 2 matrices, both the member operator and operator* are applicable and have equal precedence regarding the decision of the overload to choose.
Use concepts (or SFINAE prior to C++20) to determine, if the parameter is a matrix or a scalar. This allows you to define overloads that only take part in overload resolution for the proper parameter types.
I recommend being consistent with the location of the implementation of the operator btw: If you implement a symetric operator where one of the overloads need to be defined at namespace scope, define both overloads at namespace scope; this allows you to keep the logic of both versions close together making it easier to maintain the logic.
In the following case we simply define everything that's not a matrix a scalar.
template<class T>
struct Matrix
{
};
template<class T>
struct IsMatrixHelper : std::false_type {};
template<class T>
struct IsMatrixHelper<Matrix<T>> : std::true_type {};
template<class T>
concept Scalar = !IsMatrixHelper<T>::value;
template<class T, Scalar U>
auto operator*(Matrix<T> const& m, U scalar)
{
return Matrix<decltype(std::declval<T>()* std::declval<U>())>{};
}
template<Scalar T, class U>
auto operator*(T scalar, Matrix<U> const& m)
{
return Matrix<decltype(std::declval<T>()* std::declval<U>())>{};
}
template<class T, class U>
auto operator*(Matrix<T> const& m1, Matrix<U> const& m2)
{
return Matrix<decltype(std::declval<T>()* std::declval<U>())>{};
}
static_assert(std::is_same_v<decltype(std::declval<Matrix<int>>() * std::declval<Matrix<long long>>()), Matrix<long long>>);
static_assert(std::is_same_v<decltype(std::declval<Matrix<long long>>() * std::declval<int>()), Matrix<long long>>);
static_assert(std::is_same_v<decltype(std::declval<long long>() * std::declval<Matrix<int>>()), Matrix<long long>>);

matrix class template,the multiplication or addition of different types of matrices

I am writing a matrix class template. I want to implement the multiplication or addition of different types of matrices( for example, between real and imaginary matrices ), but I cannot access the data members of another type of matrix. How should I solve this problem?
template <class Type>
class Matrix
{
Type** p_data; //Represents matrix data
int row, col; //Represents the number of rows and columns of the matrix
public:
Matrix(int r, int c);
~Matrix();
Matrix(Type *data, int row, int col);
Type* operator[] (int i);
// Overload [], for Matrix object M, can be accessed by M [I] [J] to
// access the i + 1 line, the J + 1 column element
Matrix &operator = (const Matrix& m);
// Overload =, implement matrix overall assignment, if the row / column does not wait,
// return space and reassign
bool operator == (const Matrix& m) const; //Overload ==, determined whether the matrix is ​​equal
template <class Type1>
Matrix operator + (const Matrix<Type1>& m) const;
// Overload +, complete matrix addition, can assume
// that the two matrices meet the addition conditions (the rows, the columns are equal)
template <class Type1>
Matrix operator * (const Matrix<Type>& m) const;
// Overload *, complete matrix multiplication, can assume that two matrices meet multiplication
// conditions (this.col = m.row)
template <class Type1>
friend std::ostream& operator << (std::ostream& out,Matrix<Type1>& c);
};
template<class Type>
template <class Type1>
Matrix<Type> Matrix<Type>::operator + (const Matrix<Type1>& m) const{
Matrix<Type> res(row,col);
for(int i=0;i<row;++i)
for(int j=0;j<col;++j)
res.p_data[i][j] =p_data[i][j] + m.p_data[i][j]; // error in this line
return res;
}
You can use a friend declaration
template <typename T>
class Matrix
{
template <typename U>
friend class Matrix;
// ...
};

Wrong member operator is deduced over the correct global one

I have a 3x3 Matrix and a 3x1 Vector classes. I have two multiplication operators; one for multiplying a matrix with a scalar, another for multiplying a matrix with a vector object. The matrix-scalar multiplication operator is member inside the Matrix class and the matrix-vector multiplication operator is global.
#include <initializer_list>
#include <array>
template <class T>
class Matrix
{
public:
Matrix(std::initializer_list<T> List);
Matrix() : Matrix({0,0,0,0,0,0,0,0,0}) {}
template <class S> // THE COMPILER TRIES TO USE
Matrix<T> operator*(const S & Scalar); // THIS OPERATOR IN BOTH CASES.
const T & operator()(size_t i, size_t j) const;
private:
static constexpr size_t SIZE = 3;
static constexpr size_t AREA = SIZE * SIZE;
std::array<T, AREA> E;
};
template <class T>
Matrix<T>::Matrix(std::initializer_list<T> List)
{
if (List.size() != AREA) throw("Error!");
for (size_t i=0; i<AREA; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Matrix<T>::operator()(size_t i, size_t j) const
{
return E[SIZE * j + i];
}
template <class T>
template <class S>
Matrix<T> Matrix<T>::operator*(const S & Scalar)
{
const T ScalarT = static_cast<T>(Scalar);
Matrix<T> Result;
for (size_t i=0; i<AREA; i++)
{
Result.E[i] = E[i] * ScalarT;
}
return Result;
}
template <class T>
class Vector
{
public:
Vector(std::initializer_list<T> List);
Vector() : Vector({0,0,0}) {};
const T & operator()(size_t i) const;
T & operator()(size_t i);
private:
static constexpr size_t SIZE = 3;
std::array<T, SIZE> E;
};
template <class T>
Vector<T>::Vector(std::initializer_list<T> List)
{
if (List.size() != SIZE) throw("Error!");
for (size_t i=0; i<SIZE; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Vector<T>::operator()(size_t i) const
{
return E[i];
}
template <class T>
T & Vector<T>::operator()(size_t i)
{
return E[i];
}
template <class T> // THE COMPILER NEVER TRIES USING THIS GLOBAL OPERATOR.
Vector<T> operator*(const Matrix<T> & Mat, const Vector<T> & Vec)
{
Vector<T> Result;
Result(0) = Mat(0,0) * Vec(0) + Mat(0,1) * Vec(1) + Mat(0,2) * Vec(2);
Result(1) = Mat(1,0) * Vec(0) + Mat(1,1) * Vec(1) + Mat(1,2) * Vec(2);
Result(2) = Mat(2,0) * Vec(0) + Mat(2,1) * Vec(1) + Mat(2,2) * Vec(2);
return Result;
}
int wmain(int argc, wchar_t *argv[]/*, wchar_t *envp[]*/)
{
Matrix<float> Mat1({2, 0, 0,
0, 2, 0,
0, 0, 2});
Vector<float> Vec1({1,
2,
3});
Matrix<float> Mat2 = Mat1 * 2; // Matrix-Scalar Multiplication
Vector<float> Vec2 = Mat1 * Vec1; // Matrix-Vector Multiplication
return 0;
}
The problem is, when I try to do a matrix-vector multiplication, the compiler chooses and tries to use the matrix-scalar multiplication operator, and gives a compiler error.
If I delete the matrix-scalar multiplication operator and the line where I use it, the program runs successfully. In reverse, if I delete the matrix-vector multiplication operator, it again runs successfully. They just don't get along. And when it runs (in either case), it makes the all calculations correctly.
What is going wrong here?
Compiler & IDE: Microsoft Visual Studio 2015 Community Edition
The language doesn't specify that when searching for overloads to examine all possible scopes. As soon as one candidate is found, only the overloads in that scope are used to select the best candidate. If that candidate fails to compile for other reasons, it still won't examine additional scopes.
So in your case since the scalar is a template parameter it will match any type so as long as the left-hand operand of the operator is a Matrix<T>, the scalar multiplication will match any right-hand operand.
You could:
Just make both operator* at the same scope so they're both considered for overload resolution.
Change the scalar operator to take for example a Scalar<T> that's a thin wrapper around a scalar type rather than a generic template type.

unable to match function definition to an existing declaration in cpp

I'm doing a course project and I created a matrix class with 2d vector in cpp.
I'm trying to override * operator to an global operator with the matrix obj.
this is my declaration:
friend Matrix<T> operator * (T t, const Matrix<T> &m);
and this is the function:
template <typename T>
Matrix<T> operator * (T t, const Matrix<T> &m)
{
int i, j;
Matrix<T> ans(rows, cols);
for (i = 0; i < rows; i++)
{
for (j = 0; j < rows; j++)
{
ans[i][j] = t * m.mat[i][j];
}
}
return ans;
}
my error is: error C2244: 'Matrix::operator *' : unable to match function definition to an existing declaration
what is wrong with my code??
The friend function you declared, though in class, is not a member function.
Adjust the definition like this:
template <typename T>
Matrix<T> operator * (T t, const Matrix<T> &m)
{
// […]
}

Overloading of operators with class instance as right-hand side

I'm trying to do overload to * operator in my Matrix class.
I have one that make it if it is Matrix*something, (int, double...)
i'm searching for one that make it for the opposite side i.e something*Matrix
this is what i tried
template<class T>
bool operator*(Matrix<T>& other ){
Matrix<T> mat(other.rows,other.columns);
for(int i=0;i<other.rows;i++){
for(int j=0;j<other.columns;j++){
T temp=other.get(i,j);
temp=temp*(this);
mat.set(i,j,temp);
}
}
return mat;
}
and this is what works for Matrix*something
Matrix<T>& operator*(const T & num){
Matrix<T> mat(rows,columns);
for(int i=0;i<rows;i++){
for(int j=0;j<columns;j++){
T temp=(matrix[i][j]);
temp=temp*num;
mat.set(i,j,temp);
}
}
return mat;
}
You should make it a non-member, that is you write outside of Matrix class:
template<class T>
Matrix<T> operator*(const T& num, const Matrix<T>& mat) {
return mat * num; // invoke existing implementation of Matrix * something
}
Note that operator* should return result by value. There is a bug in your implementation, you return dangling reference to a local variable mat.
Note that this form requires num to be of type T so if, like in your example, you have
Matrix<Rational> mat;
mat = 3 * mat;
it won't compile because 3 is not Rational.
What you can do is use identity trick to put num parameter in non-deduced context, so it will be converted from int to Rational:
template<class T>
Matrix<T> operator*(typename boost::mpl::identity<T>::type const& num, const Matrix<T>& mat) {
return mat * num; // invoke existing implementation of Matrix * something
}
Where identity is just
template<typename T>
struct identity { typedef T type; };
Or you can do just
template<class T, class U>
Matrix<T> operator*(const U& num, const Matrix<T>& mat) {
return mat * num; // invoke existing implementation of Matrix * something
}