I have a simple Matrix class that I must read/write from in the format a[index1][index2]
.
For example:
Matrix a;
a[1][2] = 5;
How would I implement that in C++? thanks.
I have a simple Matrix class that I must read/write from in the format a[index1][index2]
.
For example:
Matrix a;
a[1][2] = 5;
How would I implement that in C++? thanks.
Here's a nice base implementation that does exactly what you want.
Update (September 26, 2013): I have improved the code quite a lot.
The type T
in the template only needs to satisfy the requirements of an std::vector
.
#include <vector>
#include <stdexcept>
template<typename T>
class matrix {
class row {
std::vector<T> values;
public:
row(std::size_t n)
: values(n, T()) {}
T& operator[] (std::size_t index) {
if (index < values.size())
return values[index];
else
throw std::domain_error("Matrix column index out of bounds.");
}
const T& operator[] (std::size_t index) const {
if (index < values.size())
return values[index];
else
throw std::domain_error("Matrix column index out of bounds.");
}
std::size_t size() const { return values.size(); }
};
std::vector<row> rows;
public:
matrix(std::size_t m, std::size_t n)
: rows(m, row(n)) {}
row& operator[](std::size_t index) {
if (index < rows.size())
return rows[index];
else
throw std::domain_error("Matrix row index out of bounds.");
}
const row& operator[](std::size_t index) const {
if (index < rows.size())
return rows[index];
else
throw std::domain_error("Matrix row index out of bounds.");
}
std::size_t row_count() const { return rows.size(); }
std::size_t col_count() const {
if (rows.size()) return rows[0].size();
return 0;
}
std::size_t size() const { return row_count() * col_count(); }
};
For convenience, this helper can be used to print a matrix.
#include <ostream>
template<typename T>
std::ostream& operator <<(std::ostream& o, const matrix<T>& mat) {
for (std::size_t i = 0u; i < mat.row_count(); ++i) {
for (std::size_t j = 0u; j < mat.col_count(); ++j) {
o << mat[i][j] << ' ';
}
o << '\n';
}
return o;
}
And just for you, a usage example to test this:
int main() {
matrix<int> mat_0(2, 3);
matrix<double> mat_1(1, 2);
mat_0[0][0] = 2;
mat_0[0][1] = 3;
mat_0[0][2] = 4;
mat_0[1][0] = 3;
mat_0[1][1] = 7;
mat_0[1][2] = 9;
mat_1[0][0] = 0.43;
mat_1[0][1] = 213.01;
std::cout << mat_0;
std::cout << '\n';
std::cout << mat_1;
return 0;
}
You need to overload Matrix::operator[]
so that it returns a helper class that represents a column in your matrix. That helper class should also overload operator[]
to access an element within that column.
However, implementing it this way can be overcomplicated. Instead, it might be easier to implement operator()
and have it take the two indices as arguments:
int& Matrix::operator()(int i, int j)
{
return internal_array[i][j];
}
Define a nested class RowType
with operator[]
returning a ref to a Matrix
element, and define the Matrix
operator []
to return a ref to an elemt of RowType
.
Here is a variation on the thema (around the first answer). I just belive you shuld not use new-delete.. ah, and a template, to use int, double, complex, (string!?) etc. This is not a full implemetation and I have not debugged it. It is just an idea.
#include <vector>
template <typename Num>
class Matrix {
public:
class RowType
{ public:
RowType () { }
RowType (unsigned int columnCount):values(columnCount,Num()) {}
int& operator[](unsigned int index) {return values[index];}
const int& operator[](unsigned int index)const{return values[index];}
std::vector<Num> values;
};
Matrix() { }
Matrix(unsigned int rowCount, unsigned int columnCount)
:rows(rowCount, MatrixRow<Num>(columnCount) ) {}
RowType& operator[](unsigned int index) {return rows[index]);}
const RowType& operator[](unsigned int index)const{return rows[index]);}
private: std::vector<RowType<Num>> rows;
};
....
Matrix<int> a(10,10);
a[9][9]=1;
You could create a 1d Matrix class, e.g. Matrix1D
and overload its []
operator to give you access to the value at a specific index.
Then you could create a 2d Matrix class, e.g. Matrix2D
and overload its []
operator to give you access to one of the Matrix1D
class contained in it.
That way you'd transition from a
(Matrix2D
) to Matrix1D
with []
and then to the value with the 2nd []
.