This error is occurring when I am doing scalar multiplication. I am using template classes to perform these operations on matrices. I have been trying to grasp at the concepts, but I seem to be failing. Any help is appreciated.
main.cpp inside main function
Matrix<int, 3, 3> m4;
Matrix<int, 3, 3> m5(3);
m5 = m4 * 2; //This works
m5 = 2 * m4; //Gives an error for this
cout << m5 << endl;
matrix.h
#include <exception>
template <class T, int M, int N>
Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);
template <class T, int M, int N>
class Matrix
{
private:
T mat[M][N];
int rows = M;
int cols = N;
public:
// Error class
class IllegalOperation : public std::exception
{
public:
IllegalOperation(const char *msg) : _msg(msg) {}
virtual const char *what() const throw() { return _msg.c_str(); };
private:
std::string _msg;
};
// constructor
Matrix(int v = 0)
{
for (int i = 0; i < M; i )
{
for (int j = 0; j < N; j )
mat[i][j] = v;
}
}
// () overloading
T &operator()(int i, int j)
{
return mat[i][j];
}
const T &operator()(int i, int j) const
{
return mat[i][j];
}
// [] overloading
T *operator[](int index)
{
return mat[index];
}
const T *operator[](int index) const
{
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, N1> operator*(Matrix<T1, M1, N1> const &other);
template <class T1, int M1, int N1>
const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
Matrix<T, M, N> operator (Matrix<T, M, N> const &other);
// scalar
Matrix<T, M, N> operator*(T);
friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &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, N> 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 IllegalOperation("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, N1> Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other)
{
std::cout << M << " " << N1;
if (N == M1)
{
Matrix<T, M, N1> 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 IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}
template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> const Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other) const
{
if (N == M1)
{
Matrix<T, M, N1> 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 IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}
Function for m * 2
, and this works
// scalar m * T
template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
{
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];
if (scalar == 0)
resultantMatrix(i, j) = 0;
// else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
// throw std::out_of_range("Resultant value of matrix is out of range");
else
resultantMatrix(i, j) = this->mat[i][j] * scalar;
}
}
return resultantMatrix;
}
Function for 2 * m
, this does not work
template <class T, int M, int N>
Matrix<T, M, N> operator*(T scalar, const Matrix<T, M, N> &other)
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < M; i )
{
for (auto j = 0; j < N; j )
{
auto valueFirst = other(i, j);
if (scalar == 0)
resultantMatrix(i, j) = 0;
// else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
// throw std::out_of_range("Resultant value of matrix is out of range");
else
resultantMatrix(i, j) = other(i, j) * scalar;
}
}
return resultantMatrix;
}
Errors
In file included from main.cpp:3:
matrix.h:4:1: error: ‘Matrix’ does not name a type
4 | Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);
| ^~~~~~
matrix.h: In instantiation of ‘class Matrix<int, 3, 2>’:
main.cpp:10:29: required from here
matrix.h:76:28: error: template-id ‘operator*<>’ for ‘Matrix<int, 3, 2> operator*(int, const Matrix<int, 3, 2>&)’ does not match any template declaration
76 | friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
| ^~~~~~~~~~~
matrix.h:210:17: note: candidates are: ‘Matrix<T, M, N> Matrix<T, M, N>::operator*(T)’
210 | Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
| ^~~~~~~~~~~~~~~
matrix.h:71:28: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> const Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&) const’
71 | const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
| ^~~~~~~~
matrix.h:69:22: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&)’
69 | Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
| ^~~~~~~~
matrix.h: In instantiation of ‘class Matrix<int, 3, 3>’:
main.cpp:12:25: required from here
matrix.h:76:28: error: template-id ‘operator*<>’ for ‘Matrix<int, 3, 3> operator*(int, const Matrix<int, 3, 3>&)’ does not match any template declaration
76 | friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
| ^~~~~~~~~~~
matrix.h:210:17: note: candidates are: ‘Matrix<T, M, N> Matrix<T, M, N>::operator*(T)’
210 | Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
| ^~~~~~~~~~~~~~~
matrix.h:71:28: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> const Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&) const’
71 | const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
| ^~~~~~~~
matrix.h:69:22: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&)’
69 | Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
CodePudding user response:
You need to forward declare your class before you use it, like this.
template <class T, int M, int N>
class Matrix;
template <class T, int M, int N>
Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);
template <class T, int M, int N>
class Matrix
{
...
};
A simpler option would be to remove the declaration of operator*
and just define it after the definition of Matrix
. Like this
template <class T, int M, int N>
class Matrix
{
...
};
template <class T, int M, int N>
Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &)
{
...
}
but maybe that will cause problems elsewhere in your code, I can't see enough of it to tell.