I am trying to build a templated Matrix class in C++. Below is its implementation. I implemented two operators +,+= as of now just to give an idea on how it will look and I thought it would be best to ask for feedback before I proceed any further.
The whole implementation is public and also there are no explicit bound/error checks, this is because its not meant to be a full fledged matrix library and hence avoided unnecessary code.
It would be very helpful if someone could comment on it and may be suggest a few improvements or suggestions.
Thank you.
template<class T>
class Matrix
{
public:
int r,c;
vector< vector< T > >mat;
Matrix() {}
// Constructor to set the size of the matrix
Matrix(int _r,int _c)
{
r=_r;c=_c;
mat.resize(r);
for(int i=0;i<r;i++)
mat[i].resize(c);
}
// Constructor to build a matrix from a C 2d array
// Pointer to the first element is passed (&arr[0][0])
Matrix(T *arr,int _r,int _c)
{
r=_r;c=_c;
mat.resize(r);
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
mat[i].push_back(arr[i*c+j]);
}
template<typename U>
Matrix<T>& operator +=(const Matrix<U>&M)
{
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
mat[i][j]+=static_cast<T>(M.mat[i][j]);
return *this;
}
template<typename U>
Matrix<T> operator +(const Matrix<U>&M)
{
Matrix<T>tmp=*this;
return tmp+=M;
}
};
template<typename T>
istream& operator >>(istream &in,Matrix<T>&M)
{
in>>M.r>>M.c;
Matrix<T>tmp(M.r,M.c);
for(int i=0;i<M.r;i++)
for(int j=0;j<M.c;j++)
in>>tmp.mat[i][j];
M=tmp;
return in;
}
template<typename T>
ostream& operator <<(ostream &out,Matrix<T>M)
{
for(int i=0;i<M.r;i++)
{
for(int j=0;j<M.c;j++)
cout<<M.mat[i][j]<<" ";
cout<<endl;
}
return out;
}
EDIT: Thank you all for the suggestions.
I just have one small question, say I do want to implement error checking (ex: checking for bounds,valid arguments etc..) however I do want the provide user with an option to disable error checking completely, is there any good way to implement this ? What I need is something like example:`ios_base::sync_with_stdio(0);. Thanks again.
You're wasting your time keeping
_r
and_c
because the vectors keep their own sizes.If you want to know how it's done properly, see the Eigen project's implementation:
https://bitbucket.org/eigen/eigen/src/49e00a2e570c/Eigen/src/Core/Matrix.h
https://bitbucket.org/eigen/eigen/src/49e00a2e570c/Eigen/src/Core/MatrixBase.h
Eigen is a template-heavy fast matrix library for C++. I'm sure there's a lot of usefulness there.
1 .Use initializer lists for constructor like,
Matrix (...) : r(_r), c(_c)
2.
operator +
can be simply{ return this->Add(M) }
(assuming that typenamesT
andU
are compatible and you have implemented some Add() method). 3. If you are constructing something from 2D array then use below technique:Thus you don't have to pass the size of the 2D array when you are calling and it will reduce the probability of errors.
this->r
ort_r
.I wonder why you used the very expensive push_back function in this Class initialization:
Since you already have the number of rows and columns, consider this:
If speed is what you have in mind, don't implement a matrix library yourself but use Boost libraries, I've used them in some projects and do pretty well on both 32 and 64 bit architectures
I wouldn't use a vector of vectors to achieve this. This way you're adding quite some overhead to all lookups without any real need for it. Just allocate a one or two dimensional array of
T
and use that one within your class instead. This would also allow fast copying to other object instances without having to iterate through all fields as well as resetting the whole matrix.Also you should make your members const when they shouldn't be changed later on (in your example
r
andc
). To initialize them just use the constructor list in Tony's post.