I'm having a problem to make the code:
void main(){
Matrix c(rows,cols);//rows & cols are int numbers
c[0][0]=2//the line that I'm having a problem to do the operator
}
//My class defined like this:
class Matrix{
public:
Matrix(int rows,int cols): rows(rows), cols(cols){
mat= new double*[cols];
for( int i=0; i<rows;i++){
*mat=new double[i];
}
}
private:
int rows,cols;
double **mat;
};
How can I make an operator that will help me to do the line that I'm having a problem with?
There are no operator [][]
, but operator[]
. So that one should return something for which you can use []
too (pointer or proxy class).
In your case, you might simply do:
double* operator[](int i) { return mat[i]; }
const double* operator[](int i) const { return mat[i]; }
For more complicated cases, you have to return a proxy class.
Don't dynamically allocate in two dimensions like that. It's poison for your cache, and completely pointless. I see it all the time and I wish I didn't! Make yourself a nice std::vector<double>
of size rows*cols
instead.
Anyway, the trick to permit [width][height]
is a proxy class. Have your operator[]
return an instance of a class that has its own operator[]
to do the second-level lookup.
Something like this:
#include <iostream>
#include <vector>
struct Matrix
{
Matrix(const size_t columns, const size_t rows)
: columns(columns)
, rows(rows)
, data(columns*rows, 0)
{}
size_t index(const size_t x, const size_t y) const
{
return x + y*columns;
}
double& at(const size_t x, const size_t y)
{
return data[index(x, y)];
}
double at(const size_t x, const size_t y) const
{
return data[index(x, y)];
}
template <bool Const>
struct LookupHelper
{
using ParentType = std::conditional_t<Const, const Matrix, Matrix>;
using ReturnType = std::conditional_t<Const, double, double&>;
LookupHelper(ParentType& parent, const size_t x) : parent(parent), x(x) {}
ReturnType operator[](const size_t y)
{
return parent.data[parent.index(x, y)];
}
const ReturnType operator[](const size_t y) const
{
return parent.data[parent.index(x, y)];
}
private:
ParentType& parent;
const size_t x;
};
LookupHelper<false> operator[](const size_t x)
{
return {*this, x};
}
LookupHelper<true> operator[](const size_t x) const
{
return {*this, x};
}
private:
const size_t columns, rows;
std::vector<double> data;
};
int main()
{
Matrix m(42, 3);
m[15][3] = 1;
std::cout << m[15][3] << '\n';
}
(In reality, you'd want to make it moveable and it could doubtlessly be tidied up a bit.)
Certainly, switching to operator()
or a .at(width, height)
member function is a lot easier…