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.
Use initialization lists when initializing contructor args:
..
should be:
A couple of points:
std::vector<T>
instead ofstd::vector<std::vector<T>>
. Index it with y*r+x - use and operator overload to make this easier (see next point). This will be more memory efficient and slightly faster (and your init will be a lot easier:resize(r*c)
).r
andc
.operator()
to access the matrix (both const and non-const). If you really must use thematrix[r][c]
syntax instead ofmatrix(r,c)
, consider overloadingoperator[]
and returning an iterator to the correct row (vector iterators are random access, so they will provideoperator[]
).operator+
as a non-friend non-member function instead - Improves encapsulation!T*
take an iterator instead. That way you automagically get the pointers support along with a lot of other cool things, such as range checking for debug-iterators, automatic type conversion for compatible value types and support for all other random access iterators. Also consider filling your matrix row-wise, so you can use forward iterators too.r
,c
andmat
members private.operator<<
doesn't write outr
andc
).