I got a homework which looks something like this. I am working on it and hold beginner knowledge of the same. I have to create a header file that contains this code and then use the header file to get the desired results.
I am working with C template, and operator overloading.
#include <iostream>
#include <memory>
#include "matrix.h"
#include "symetric_matrix.h"
using namespace std;
int main()
{
const Matrix<int, 3, 2> m1; // Creates 3*2 matrix, with all the default elements set to 0;
cout << m1 << endl;
Matrix<int, 3, 3> m2(4); // Creates 3*3 matrix, with the default elements equals to 4;
cout << m2 << endl;
const Matrix<int, 3, 3> m3 = m2; // C-py constructor may take O(MN) and not O(1).
cout << m3 << endl;
// min() returns the minimal value in the matrix.
if (min(m1) < min(m3))
cout << "Min value of m3(" << min(m3) << ") is bigger than min value of m1(" << min(m1) << ")" << endl;
if (m1.avg() < m3.avg()) // Compares the average of the elements
cout << "Average value of m3(" << m3.avg() << ") is bigger than average value of m1(" << m1.avg() << ")" << endl;
m2(0, 0) = 13;
cout << m2[0][0] << " " << m2[1][0] << endl; // Should print "13 4"
try
{
cout << m2 m3 << endl;
cout << m3 * m1 << endl; // You can choose the format of matrix printing;
cout << m1 * m2; // This should throw an exception
}
catch (const Matrix<int, 3, 2>::IllegalOperation &e)
{
cout << e.what() << endl;
}
Matrix<int, 3, 3> m4;
m4 = m3;
cout << m4 << endl;
for (int i = 0; i < 3; i)
for (int j = 0; j < 3; j)
m4(i, j) = i j;
cout << m4 << endl;
cout << "m4[1][1] = " << m4[1][1] << endl;
cout << "m4[1][1] = " << m4(1, 1) << endl; // m4(1,1) same result as m4[1][1]
Matrix<int, 3, 3> m5(3);
m5 = 2 * m4;
cout << m5 << endl;
Matrix<int, 3, 3> m6(m4);
cout << m6 << endl;
m5 = m4;
cout << m5 << endl;
if (m6 != m5)
cout << "m6 != m5" << endl;
Matrix<Matrix<int, 3, 2>, 4, 4> composite(m1); // Creates matrix, where each element is m1;
cout << composite;
unique_ptr<Matrix<int, 3, 3>> symetric_matrix(new SymetricMatrix<int, 3>(5)); // SymetricMatrix matrix 3*3 with default element equals to 5;
(*symetric_matrix)(1, 2) = 8;
cout << (*symetric_matrix)(1, 2) << " " << (*symetric_matrix)(2, 1) << endl; // Should print "8 8"
cout << (*symetric_matrix)[1][2] << " " << (*symetric_matrix)[2][1] << endl; // Should print "8 8"
(*symetric_matrix)[1][0] = 18;
cout << (*symetric_matrix)[1][0] << " " << (*symetric_matrix)[0][1] << endl; // Should print "18 18"
return 0;
}
My Updated solution for now.
template <class T, int M, int N>
class Matrix
{
private:
T mat[M][N];
int rows = M;
int cols = N;
public:
// constructor
Matrix(int v = 0)
{
for (int i = 0; i < M; i )
{
for (int j = 0; j < N; j )
mat[i][j] = v;
}
}
T &operator()(int i, int j)
{
return mat[i][j];
};
T *operator[](int index)
{
return mat[index];
};
// << overloading
friend std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &L)
{
for (int i = 0; i < M; i )
{
for (int j = 0; j < N; j )
os << L.mat[i][j] << " ";
os << "\n";
}
return os;
};
template <class T1, int M1, int N1>
Matrix<T, M, M> operator*(Matrix<T1, M1, N1> const &other);
Matrix<T, M, M> operator (Matrix<T, M, N> const &other);
friend T min(Matrix obj)
{
T result = obj.mat[0][0];
for (int i = 0; i < M; i )
{
for (int j = 0; j < N; j )
if (result < obj.mat[i][j])
result = obj.mat[i][j];
}
return result;
};
long double avg() const
{
long double result = 0;
for (int i = 0; i < M; i )
{
for (int j = 0; j < N; j )
if (result < mat[i][j])
result = result mat[i][j];
}
return result / (M * N);
}
};
template <class T, int M, int N>
Matrix<T, M, M> Matrix<T, M, N>::operator (Matrix const &other)
{
if ((this->rows == other.rows) && (this->cols == other.cols))
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < this->rows; i )
{
for (auto j = 0; j < this->cols; j )
{
auto &valueFirst = this->mat[i][j];
auto &valueSecond = other.mat[i][j];
// if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
// throw std::out_of_range("Resultant value of matrix is out of range");
// else
resultantMatrix(i, j) = valueFirst valueSecond;
}
}
return resultantMatrix;
}
else
throw std::runtime_error("Matrices cannot be added, sizes do not match");
}
template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, M> Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other)
{
if ((this->rows == other.rows) && (this->cols == other.cols))
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < this->rows; i )
{
for (auto j = 0; j < this->cols; j )
{
for (auto k = 0; k < this->cols; k )
{
auto &valueFirst = this->mat[i][k];
auto &valueSecond = other(k, j);
// if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
// throw std::out_of_range("Resultant value of matrix is out of range");
// else
resultantMatrix(i, j) = valueFirst * valueSecond;
}
}
}
return resultantMatrix;
}
else
throw std::runtime_error("Matrices cannot be added, sizes do not match");
}
I am getting an error and I don't understand why.
error: no match for call to ‘(const Matrix<int, 3, 2>) (int&, int&)’
112 | auto &valueSecond = other(k, j);
| ~~~~~^~~~~~
matrix.h:20:8: note: candidate: ‘T& Matrix<T, M, N>::operator()(int, int) [with T = int; int M = 3; int N = 2]’ (near match)
20 | T &operator()(int i, int j)
| ^~~~~~~~
matrix.h:20:8: note: passing ‘const Matrix<int, 3, 2>*’ as ‘this’ argument discards qualifiers
It only happens at this line auto &valueSecond = other(k, j);
and not this one resultantMatrix(i, j) = valueFirst * valueSecond;
, Why?
I just need help with the whole program while I try and learn! Any help is appreciated.
CodePudding user response:
As for the error message
matrix.h:20:8: note: passing ‘const Matrix<int, 3, 2>*’ as ‘this’ argument discards qualifiers
other
is const Matrix<int, 3, 2>&
. The T &operator()(int i, int j)
is implemented for non const Matrix<int, 3, 2>&
. There should be provided two versions of the operators
T &operator()(int i, int j)
{
return mat[i][j];
};
const T &operator()(int i, int j) const
{
return mat[i][j];
};
T *operator[](int index)
{
return mat[index];
};
const T *operator[](int index) const
{
return mat[index];
};
Using operator()
as a subscript operator may be confusing. It should be
T &operator[](int i, int j)
{
return mat[i][j];
};
const T &operator[](int i, int j) const
{
return mat[i][j];
};
Subscript operators usually are defined for size_t
types.