I’m trying to program matrix multiplication with the following class declaration of a matrix:
template<class T, int rows, int cols>
class matrix {
private:
T m_data[rows * cols];
int m_rows;
int m_cols;
public:
//constructors
matrix() : m_cols(rows), m_rows(cols) {
for (int i = 0; i < rows * cols; i++)
m_data[i] = T(); //default constructor of data type
}
matrix(const matrix& other) : m_cols(other.m_cols), m_rows(other.m_rows) {
for (int i = 0; i < other.size(); i++)
m_data[i] = other.m_data[i];
}
//other functions...
Here is my attempt:
matrix<T, rows, int> operator*(const matrix<T, cols, int>& RHS) const { //error referenced below refers to this line
if (m_cols != RHS.m_rows) {
throw std::invalid_argument("Matrix dimensions must match for multiplication!");
}
matrix<T, rows, int> toReturn;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < RHS.m_cols; ++j) {
toReturn(i, j) = 0;
for (int k = 0; k < cols; ++k) {
toReturn(i, j) += (*this)(i, k) * RHS(k, j);
}
}
}
return toReturn;
}
The errors I’m getting are:
Error C2993 'int': is not a valid type for non-type template parameter 'cols'
In main.cpp
, I am attempting to use the function as such:
matrix<int, 2, 2> m1;
m1.set(0, 0, 1);
m1.set(0, 1, 2);
m1.set(1, 0, 3);
m1.set(1, 1, 4);
matrix<int, 2, 1> m2;
m2.set(0, 0, 1);
m2.set(1, 0, 1);
matrix<int, 2, 1> m3 = m1 * m2;
The error I get now is:
C2679 binary '*': no operator found which takes a right-hand operand of type 'matrix<int,2,1>' (or there is no acceptable conversion)
5
You’re going in the right direction. However, using int
for a non-type template parameter makes no sense. What you’re looking for is an operator*
function template. It’s probably better to make it a free function instead of a member one:
template<class T, int rows, int dim, int cols>
matrix<T, rows, cols> operator*(const matrix<T, rows, dim>& m1, const matrix<T, dim, cols>& m2) {
matrix<T, rows, cols> res;
// calculation matrix elements of res
return res;
}
Because dimensions are encoded into a matrix type, you don’t need any runtime checks, a compiler will do it for you – there will be simply no match for operator*
if dimensions don’t agree.
Also note that because dimensions are part of a type, you don’t really need m_rows
and m_cols
data members. Use rows
and cols
template parameters.