C++ overload operator [ ][ ] - c++

I have class CMatrix, where is "double pointer" to array of values.
class CMatrix {
public:
int rows, cols;
int **arr;
};
I simply need to access the values of matrix by typing:
CMatrix x;
x[0][0] = 23;
I know how to do that using:
x(0,0) = 23;
But I really need to do that the other way. Can anyone help me with that?
At the end I did it this way...
class CMatrix {
public:
int rows, cols;
int **arr;
public:
int const* operator[]( int const y ) const
{
return &arr[0][y];
}
int* operator[]( int const y )
{
return &arr[0][y];
}
....

You cannot overload operator [][], but the common idiom here is to use a proxy class, i.e. overload operator [] on your Matrix class to return an instance of a different class which then has operator [] overloaded on it.
For example:
class CMatrix {
public:
class CRow {
friend class CMatrix;
public:
int& operator[](int col)
{
return parent.arr[row][col];
}
private:
CRow(CMatrix &parent_, int row_) :
parent(parent_),
row(row_)
{}
CMatrix& parent;
int row;
};
CRow operator[](int row)
{
return CRow(*this, row);
}
private:
int rows, cols;
int **arr;
};

There is no operator[][] in C++. However, you can overload operator[] to return another structure, and in that overload operator[] too to get the effect you want.

You can do it by overloading operator[] to return an int*, which is then indexed by the second application of []. Instead of int* you could also return another class representing a row, whose operator[] gives access to individual elements of the row.
Essentially, subsequent applications of operator[] work on the result of the previous application.

If you create a matrix using Standard Library containers, it's trivial:
class Matrix {
vector<vector<int>> data;
public:
vector<int>& operator[] (size_t i) { return data[i]; }
};

Some support for this has been added for containers in C++23: Multidimensional subscript operator
Although the syntax used is v[x, y, z] rather than v[x][y][z].

You could operator[] and make it return a pointer to the respective row or column of the matrix.
Because pointers support subscripting by [ ], access by the 'double-square' notation [][] is possible then.

Other answers tell you how you can do it, but...
Don’t do that.
Instead, overload operator ().
int & operator () ( size_t row, size_t col )
{
// maybe validate `row` and `col` first?
return arr[row * cols + col];
}
Why not?
The C++ FAQ explains it all. Straight from the horses’ mouths.
How do I create a subscript operator for a Matrix class?
Why shouldn’t my Matrix class’s interface look like an array-of-array?
I still don’t get it. Why shouldn’t my Matrix class’s interface look like an array-of-array?
tl;dr : encapsulation and safety

Related

C++ is there a way to overload operator [][]? [duplicate]

I have class CMatrix, where is "double pointer" to array of values.
class CMatrix {
public:
int rows, cols;
int **arr;
};
I simply need to access the values of matrix by typing:
CMatrix x;
x[0][0] = 23;
I know how to do that using:
x(0,0) = 23;
But I really need to do that the other way. Can anyone help me with that?
At the end I did it this way...
class CMatrix {
public:
int rows, cols;
int **arr;
public:
int const* operator[]( int const y ) const
{
return &arr[0][y];
}
int* operator[]( int const y )
{
return &arr[0][y];
}
....
You cannot overload operator [][], but the common idiom here is to use a proxy class, i.e. overload operator [] on your Matrix class to return an instance of a different class which then has operator [] overloaded on it.
For example:
class CMatrix {
public:
class CRow {
friend class CMatrix;
public:
int& operator[](int col)
{
return parent.arr[row][col];
}
private:
CRow(CMatrix &parent_, int row_) :
parent(parent_),
row(row_)
{}
CMatrix& parent;
int row;
};
CRow operator[](int row)
{
return CRow(*this, row);
}
private:
int rows, cols;
int **arr;
};
There is no operator[][] in C++. However, you can overload operator[] to return another structure, and in that overload operator[] too to get the effect you want.
You can do it by overloading operator[] to return an int*, which is then indexed by the second application of []. Instead of int* you could also return another class representing a row, whose operator[] gives access to individual elements of the row.
Essentially, subsequent applications of operator[] work on the result of the previous application.
If you create a matrix using Standard Library containers, it's trivial:
class Matrix {
vector<vector<int>> data;
public:
vector<int>& operator[] (size_t i) { return data[i]; }
};
Some support for this has been added for containers in C++23: Multidimensional subscript operator
Although the syntax used is v[x, y, z] rather than v[x][y][z].
You could operator[] and make it return a pointer to the respective row or column of the matrix.
Because pointers support subscripting by [ ], access by the 'double-square' notation [][] is possible then.
Other answers tell you how you can do it, but...
Don’t do that.
Instead, overload operator ().
int & operator () ( size_t row, size_t col )
{
// maybe validate `row` and `col` first?
return arr[row * cols + col];
}
Why not?
The C++ FAQ explains it all. Straight from the horses’ mouths.
How do I create a subscript operator for a Matrix class?
Why shouldn’t my Matrix class’s interface look like an array-of-array?
I still don’t get it. Why shouldn’t my Matrix class’s interface look like an array-of-array?
tl;dr : encapsulation and safety

Overload index operator to mimic POD multi-dimensional array?

I have an existing class, which is structured in the following way:
class Matrix
{
public:
float Data[4][4];
// ... methods
};
And subsequently used in the following ways:
Matrix m;
m.Data[0][0] = 1.0f;
float local = m.Data[0][0];
//...
I would like to replace the Data member with an overloaded indexing operator, so I can perform range checking on the indices used. While I can change the Matrix class itself, and the implementations of its member functions, I cannot modify its usages in existing code, so any solution requires that the usage syntax remains identical. It's also desirable that the solution doesn't change sizeof(Matrix). Is there a way to achieve this?
Generally for this sort of thing, you need to use a proxy class to handle the second indexing operator. It would look something like this and go in the private section of your Matrix class. I'll leave out the bounds-checking (it shouldn't be hard for you to add that yourself).
class Proxy {
Matrix& ref;
size_t i;
public:
Proxy(Matrix& on, size_t i) : ref(on), i(i) {}
float operator[] (size_t j) {
return ref.Data[i][j];
}
};
Then just have your Matrix::operator[] return an instance of this class:
Proxy operator[] (size_t i) {
return Proxy(*this, i);
}
Note that if you want a const overload (ie, you want to use the indexing operator on const Matrix objects), you'll need a separate ConstProxy class which has const Matrix& ref instead of Matrix& ref but is otherwise identical.
There is also the option of returning a reference to an array. (Note: as one of the comments pointed out, this doesn't help much with bound-checking, but I think it's interesting, so I'll leave it here.)
float (&operator[](size_t i))[4] {
return Data[i];
}
The syntax for that is quite arcane, and I believe it doesn't work in Visual Studio 2013, but you can make it a bit cleaner with a typedef.
using Proxy = float[4];
Proxy& operator[](size_t i) {
return Data[i];
}
There's one more option, if you don't mind abandoning square-bracket indexing. You can overload the function call operator like this:
float operator()(size_t i, size_t j) {
return Data[i][j];
}
Another way is define a the proxy class with the semantic of a vector
class Matrix
{
public:
struct SubMatrix
{
class Vector
{
public:
Vector(float *data) : Data(data) {}
float &operator[](int index) { return Data[index]; }
private:
float *Data;
};
Vector operator[](int index)
{
return Vector(Data[index]);
}
float Data[4][4];
};
SubMatrix Data;
// ... methods
};
Then you can use it this way:
Matrix m;
float f = m.Data[1][2];

How to recognize the assignment operator?

I've got class with overloaded [] and I need to make it to recognize, when I try to set the values to the array. I assume, that I'll have to overload the operator =, nevertheless I don't know, how shall that whole stuff look like. Part of my code:
class Matrix {
public:
Matrix(int x, int y);
~Matrix(void);
Matrix& operator =(const Matrix &matrix); //ok...this is probably wrong...
class Proxy {
public:
Proxy(double* _array) : _array(_array) {
}
double &operator[](int index) const {
return _array[index];
}
private:
double* _array;
};
Proxy operator[](int index) const {
return Proxy(_arrayofarrays[index]);
}
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
int x, y;
double** _arrayofarrays;
};
So I just need to be able to recognize when I try to set Matrix matrix(3,3); matrix[0][0]=1;
Everything else works allright, so I assumed that it's not needed to paste the whole code
It looks like you want something which is not directly possible: operator[][].
You can emulate the behavior of this by using an intermediate class:
Since a Matrix class is typically indexed as [rows][columns], you can
have the first operator method return the corresponding Row object.
The row class can than overload the operator[] and return the corresponding
element.
Row& Matrix::operator[](int r);
double& Row::operator[](int c);
Now when you create your matrix object, you can index it as expected:
Matrix matrix(3,3);
matrix[0][0] = 1;
The last line is then equivalent to calling:
matrix.operator[](0).operator[](0) = 1;
To check for out-of-bounds indices, store the matrix sizes:
Proxy operator[](int index) {
assert(index < num_rows);
return Proxy(_arrayofarrays[index]);
}
double &operator[](int index) const {
assert(index < num_cols);
return _array[index];
}
As Aldo suggeested, Proxy can be passed the array length value in it's constructor:
Proxy(double* _array, int _length) : _array(_array), num_cols(_length){
}
As a general rule of thumb, if you're passing a raw array to a function, you will almost always want to pass the length of that array as well.
Your Proxy::operator[] overload is returning a double&. This double& is the object that will eventually be assigned to by client code, and you can't intercept that (at least not easily). Probably what you need to do is to check the index parameter in your operator[] overloads, and throw your own exception there rather than passing that index along to your internal arrays.

C++ multidimensional array operator

it is possible to overload somehow operator for multidimensional array?
Something like:
class A {
...
int& operator[][] (const int x, const int y);
...
}
Nope, that is not possible. There are two alternatives, though:
You can have operator[] return an array of a smaller dimension (For a 3D array, it will return a 2D array, for a 2D array it will return a 1D array, and for a 1D array, it will return a single element). Then you can "string them together" with the syntax you want. (arr[x][y][z])
Alternatively, you can overload operator(), because that can take multiple arguments.
Then you can use it like this, to index into a 3D array for example: arr(x,y,z)
But you can't overload [][] or [][][] as a single operator.
Not directly, but you can achieve the same functionality overloading operator[]() and having it return something that supports operator[]() itself.
For example:
class A {
std::vector<std::vector<int> > vec;
public:
std::vector<int>& operator[] (int x)
{
return vec[x];
}
};
would allow you to write:
A a;
//...
int y = a[1][2];
because a[1] returns a std::vector<int> to which you can apply operator[](2).
You need to overload operator[] and make it return a new class which only has another operator[].
No, there's just operator[]. As an alternative, you can overload:
int &operator()(int x, int y);
You can use that:
m(4, 5);
Since C++23, an overloaded operator[] will now take 0 or more arguments which behaves exactly the same as operator()
class A {
// ...
int& operator[](std::size_t x, std::size_t j);
// ...
};
invocation:
A a = /* ... */;
a[1, 2]; // equivalent to 'a.operator[](1, 2)'
It is a single operator being used twice to dereference. You can dereference [] operator and perform the functionality and usage by using it as [][] by changing the return type.
There's no operator like that. I implemented, some times ago, a matrix trying to be close to the stl standards.
And I used this method: first I've overloaded the operator[] to return another class that I called _C_row:
_C_row operator[](size_type index) { return _C_row(/*some parameters*/); } ///< This operator is overloaded to permit the use of double pointer notation.
_C_row operator[](size_type index) const { return _C_row(/*some parameters*/); } ///< This operator is overloaded to permit the use of double pointer notation.
And in _C_row I overloaded more than the operator[]:
value_type operator*() { return _r[0]; }
pointer operator->() { return _i[_idx]; }
double_pointer operator&() { return &(_i[_idx]); }
reference operator[](size_type col) { return _r[col]; }
const_reference operator[](size_type col) const { return _r[col]; }
I found this solution is very flexible. I hope my answer could be useful for you.
As mentionned before, there is no such thing as operator[][].
However, here is an an implementation using nested classes similar to what "jalf" proposed. For sake of simplicity, I hardcoded a 3x3 raw array.
class Array2D final{
public:
class PartialArr final{
private:
friend Array2D;
PartialArr(Array2D* ptr, int index) :original(ptr), firstIndex(index) {}
int firstIndex;
Array2D* original;
public:
int& operator[](int index) { return this->original->data[firstIndex][index]; }
};
PartialArr operator[](int index) { return PartialArr(this, index); }
private:
int data[3][3];
};
This solution prevents the user of Array2D to manipulate the data directly when indexing only the first dimension of the array.
const versions of both operator[] could also be added to make the class complete.

Two square bracket overloading

I am writing a matrix class in c++ and trying to overload some operator like = and >> and << etc.
I was unable to overload operator [][] for matrix class.
if i have an object of class matrix like M1 then i can use this way for giving value to each element:
M1[1][2]=5;
OR
int X;
X=M1[4][5];
Just overload operator[] and make it return a pointer to the respective row or column of the matrix. Since pointers support subscripting by [], access by the 'double-square' notation [][] is possible then.
You can also overload operator() with two arguments.
There is no operator[][] in C++. You have to return a helper object and then overload operator[] for that too, to have this kind of access.
You could overload operator[]. So if you would like to use matrix that way, you should make matrix as array of vectors.
class Matrix
{
...
Vector & operator[]( int index );
...
};
and
class Vector
{
...
double & operator[]( int index );
...
};
Finally:
Matrix m;
...
double value = m[i][j];
...
there is no operator[][], you can implement operator[] to return a reference to the row/column object, in which you can implement the operator[] to return you the cell reference.
You can do something like the following to avoid all that hassle..
struct loc
{
int x;
int y;
};
then in your operator[] overload, accept a loc, something like
T& operator[](loc const& cLoc)
{
// now you have x/y you can return the object there.
}
To call, you can simply do something like:
matrix[loc(2,3)] = 5;
Actually, I did just that in my own matrix class a few years ago. In this case, I defined a matrix template class that contained the snippet, below.
I was then able to iterate and assign as follows:
for(size_t k=1; k<n; ++k) {
minor[p][k-1]=major[j][k];
}
I hope this helps.
// //////////////////////////////////////////////////////////////////////////////
// list is internal vector representation of n x m matrix
T* list;
// Proxy object used to provide the column operator
template < typename T >
class OperatorBracketHelper
{
Matrix < T > & parent ;
size_t firstIndex ;
public :
OperatorBracketHelper ( Matrix < T > & Parent , size_t FirstIndex ) :
parent ( Parent ), firstIndex ( FirstIndex ) {}
// method called for column operator
T & operator []( size_t SecondIndex )
{
// Call the parent GetElement method which will actually retrieve the element
return parent.GetElement ( firstIndex , SecondIndex );
}
};
// method called for row operator
OperatorBracketHelper < T > operator []( size_t FirstIndex )
{
// Return a proxy object that "knows" to which container it has to ask the element
// and which is the first index (specified in this call)
return OperatorBracketHelper < T >(* this , FirstIndex );
}
T & GetElement ( size_t FirstIndex , size_t SecondIndex )
{
return list[FirstIndex*cols+SecondIndex];
}
I am exactly working on a matrix class and I decided to first create an Array class which has a dynamic 2-D array. So, well just as you, I confronted this obstacle that how I can overload two square brackets. How I approached this case is very simple; I overloaded the square brackets operator twice as member functions. First, I overloaded [] so as to return a pointer pointing to the desired row, so to speak, and then the following member function (i.e. again operator [] overloaded) returns a lvalue of the same type as the array's elements.
However, note that the index you inter to invoke the former overloaded operator [] must be saved somewhere so that you may use it in the latter overloaded operator []. For this reason I simply added a new member of the type int to the class Array (which I've named it "test" in my code below).
class Array {
private:
double **ptr; int test;
... /* the rest of the members includes the number of rows and columns */
public:
Array(int=3,int=3); // Constructor
Array(Array &); // Copy Constructor
~Array(); // Destructor
void get_array();
void show_array();
double* operator[] (int);
double operator[] (short int);
...
};
...
double* Array::operator[] (int a) {
test = a;
double* p = ptr[test];
return p;
}
double Array::operator[] (short int b) {
return ((*this)[test][b]);
}
Therefor, as an example, in main I can simply write:
int main(){
Array example;
cout << example[1][2];
}
I hope this would help you.
You can't overload [][] as such, since there isn't such an
operator. You can overload [] to return something which also
has an [] defined on it (a proxy); in the simplest case,
something like a double* will work, but it's usually better,
although a bit more work, to use a full class. (Place to add
bounds checking, for example.)
Alternatively, you can overload (x,y). Depending on who you
ask, one format or the other is "better". (In fact, it's
strictly a question of style.)
Template matrix class
template <uint8_t rows, uint8_t cols, typename T>
class MatrixMxN {
public:
T* operator[](uint8_t f_row) {
return &m_val[f_row * cols];
}
protected:
T m_val[rows*cols];
};
and here is object of matrix with 3 row, 4 column and integer type.
MatrixMxN<3, 4, int32_t> M;
M[2][3] = 10;
std::cout << M[2][3] << std::endl;