Reputation: 501
I have written the following Matrix class:
template <typename T, size_t r, size_t c> //r=rows,c=cols of the Matrix
class Matrix {
public:
size_t row = 0;
size_t col = 0;
T *data;
template <size_t L>
Matrix<T, r, L> operator*(const Matrix<T, c, L> &other) const;
template <size_t r, size_t c>
Matrix &operator=(const Matrix<T, r, c> &other)
// ...
};
I overrode some operators to do some basic arithmetic and everything seems to work properly - however there is an issue which I don't know how to address properly: Given the following lines of code:
Matrix<double, 1, 4> m1(1.2);
Matrix<double, 4, 1> m2(1.2);
Matrix<double, 2, 2> m3; // problematic line
m3 = m1 * m2;
m3
is of type Matrix<double, 2, 2>
, is correctly computed, has one row and one col and carries the 5.76
, but stays as Matrix<double, 2, 2>
. The change of its number of rows and cols is not reflected in its template parameters. Naturally however I would expect the type to be also informative regarding its content.
I don't suppose one cannot turn a Matrix<double, 2, 2>
suddenly into a Matrix<double, 1, 1>
Matrix, but maybe there is a good solution I just cannot think of now.
And replace:
template <size_t r, size_t c> void replace(const Matrix<T, r, c> &other) {
delete[] data;
row = other.row; //number of rows of a matrix
col = other.col; //number of cols of a matrix
data = new T[col * row]; // data contains all the elements of my matrix
for (size_t i = 0; i < row * col; i++)
data[i] = other.data[i];
}
Upvotes: 1
Views: 109
Reputation: 40060
From your declaration
template <typename T, size_t r, size_t c> //r=rows,c=cols of the Matrix
class Matrix {
public:
template <size_t L>
Matrix<T, r, L> operator*(const Matrix<T, c, L> &other) const;
template <size_t r, size_t c> // BEWARE: shadowing
Matrix &operator=(const Matrix<T, r, c> &other);
// ...
};
we can guess what happens.
Matrix<double, 1, 4> m1(1.2);
Matrix<double, 4, 1> m2(1.2);
m1 * m2; // (1)
(1)
calls Matrix<double, 1, 4>::operator*<1>(Matrix<double, 4, 1> const&)
. It result has then type Matrix<double, 1, 1>
.
Matrix<double, 2, 2> m3;
m3 = /* (2) */ m1 * m2;
(2)
calls Matrix<double, 2, 2>::operator=<1, 1>(Matrix<double, 1, 1> const&)
. This is a problem.
A solution would be to ensure operator=
can only be called with another matrix of the right size:
template <typename T, size_t r, size_t c> //r=rows,c=cols of the Matrix
class Matrix {
public:
template <size_t L>
Matrix<T, r, L> operator*(Matrix<T, c, L> const& other) const;
Matrix &operator=(Matrix const& other);
// ...
};
You could even allow type conversions:
template<class U>
Matrix &operator=(Matrix<U, r, c> const& other);
Finally, you might want to use auto
:
Matrix<double, 1, 4> m1(1.2);
Matrix<double, 4, 1> m2(1.2);
auto m3 = m1 * m2; // m3 is Matrix<double, 1, 1>
Upvotes: 3