overloading [][]

Discussion in 'C++' started by Andre, Aug 24, 2003.

  1. Andre

    Andre Guest

    Hi,

    I have a class which contains a two-dimensional array. I need to
    overload something like the [][] operator so that I'm able to access the
    internal array elements via the class object. For example:

    Matrix a = new Matrix(10,10);

    a[1][1] = 6;

    Is this possible? How can I simulate a two dimensional array using a
    class in c++? Thanks

    -Andre
     
    Andre, Aug 24, 2003
    #1
    1. Advertising

  2. "Andre" <> wrote in message
    news:...
    > Hi,
    >
    > I have a class which contains a two-dimensional array. I need to
    > overload something like the [][] operator so that I'm able to access the
    > internal array elements via the class object. For example:
    >
    > Matrix a = new Matrix(10,10);
    >
    > a[1][1] = 6;
    >
    > Is this possible? How can I simulate a two dimensional array using a
    > class in c++? Thanks
    >
    > -Andre
    >


    There is no operator[][], there is only the operator[]. You can do what you
    want with a proxy class, something like this

    class Proxy
    {
    public:
    double operator[](int j) const;
    double& operator[](int j);
    };

    class Matrix
    {
    public:
    const Proxy operator[](int i) const;
    Proxy operator[](int i);
    };

    I hope you get the idea, you overload operator[] on your Matrix object to
    return another class (the Proxy class), you then overload operator[] on the
    proxy class to return a Matrix element.

    john
     
    John Harrison, Aug 24, 2003
    #2
    1. Advertising

  3. Andre

    Andre Guest

    Neat :) thatnks, I get the idea.

    cheers

    -Andre

    John Harrison wrote:

    > "Andre" <> wrote in message
    > news:...
    >
    >>Hi,
    >>
    >>I have a class which contains a two-dimensional array. I need to
    >>overload something like the [][] operator so that I'm able to access the
    >>internal array elements via the class object. For example:
    >>
    >>Matrix a = new Matrix(10,10);
    >>
    >>a[1][1] = 6;
    >>
    >>Is this possible? How can I simulate a two dimensional array using a
    >>class in c++? Thanks
    >>
    >>-Andre
    >>

    >
    >
    > There is no operator[][], there is only the operator[]. You can do what you
    > want with a proxy class, something like this
    >
    > class Proxy
    > {
    > public:
    > double operator[](int j) const;
    > double& operator[](int j);
    > };
    >
    > class Matrix
    > {
    > public:
    > const Proxy operator[](int i) const;
    > Proxy operator[](int i);
    > };
    >
    > I hope you get the idea, you overload operator[] on your Matrix object to
    > return another class (the Proxy class), you then overload operator[] on the
    > proxy class to return a Matrix element.
    >
    > john
    >
    >
     
    Andre, Aug 24, 2003
    #3
  4. Andre

    Sim Guest

    Just wondering.. what does they "const" in front of a function do:

    double operator[](int j) const;

    Thanks

    Sim


    John Harrison wrote:

    > "Andre" <> wrote in message
    > news:...
    >
    >>Hi,
    >>
    >>I have a class which contains a two-dimensional array. I need to
    >>overload something like the [][] operator so that I'm able to access the
    >>internal array elements via the class object. For example:
    >>
    >>Matrix a = new Matrix(10,10);
    >>
    >>a[1][1] = 6;
    >>
    >>Is this possible? How can I simulate a two dimensional array using a
    >>class in c++? Thanks
    >>
    >>-Andre
    >>

    >
    >
    > There is no operator[][], there is only the operator[]. You can do what you
    > want with a proxy class, something like this
    >
    > class Proxy
    > {
    > public:
    > double operator[](int j) const;
    > double& operator[](int j);
    > };
    >
    > class Matrix
    > {
    > public:
    > const Proxy operator[](int i) const;
    > Proxy operator[](int i);
    > };
    >
    > I hope you get the idea, you overload operator[] on your Matrix object to
    > return another class (the Proxy class), you then overload operator[] on the
    > proxy class to return a Matrix element.
    >
    > john
    >
    >
     
    Sim, Aug 24, 2003
    #4
  5. "Sim" <> wrote in message
    news:3f49163f$...
    > Just wondering.. what does they "const" in front of a function do:
    >
    > double operator[](int j) const;
    >
    > Thanks
    >
    > Sim
    >


    It means that the function does not modify the object and therefore that the
    function can be called on a const object.

    E.g.

    struct X
    {
    void f();
    void g() const;
    };

    const X x;
    x.f(); // error
    x.g(); // ok

    Functions which do not modify objects should almost always be declared
    const. const objects don't get used much, but const references are very
    common.

    john
     
    John Harrison, Aug 24, 2003
    #5
  6. "John Harrison" <> wrote in
    news:bib1jv$798kd$-berlin.de:

    >
    > "Andre" <> wrote in message
    > news:...
    >> Hi,
    >>
    >> I have a class which contains a two-dimensional array. I need to
    >> overload something like the [][] operator so that I'm able to access
    >> the internal array elements via the class object. For example:
    >>
    >> Matrix a = new Matrix(10,10);
    >>
    >> a[1][1] = 6;
    >>
    >> Is this possible? How can I simulate a two dimensional array using a
    >> class in c++? Thanks
    >>
    >> -Andre
    >>

    >
    > There is no operator[][], there is only the operator[]. You can do
    > what you want with a proxy class, something like this
    >
    > class Proxy
    > {
    > public:
    > double operator[](int j) const;

    const double&
    > double& operator[](int j);
    > };
    >
    > class Matrix
    > {
    > public:
    > const Proxy operator[](int i) const;

    ^^^^^
    const Proxy & and
    > Proxy operator[](int i);

    Proxy& will have better performance, plus, you can have the
    proxyclass save a reference to your data matrix-row and I would make this
    class inside the Matrix namespace to avoid name collisions with other
    Proxy classes for different multi-dimensional arrays.
    > };


    References combined with inline functions will have improved performance,
    since there will be no copy-constructor and destructor calls, less
    overhead.
     
    Immanuel Albrecht, Aug 24, 2003
    #6
  7. Andre

    Sim Guest

    Thanks. That clears it :)

    Sim

    Gianni Mariani wrote:
    > Sim wrote:
    >
    >> Just wondering.. what does they "const" in front of a function do:
    >>
    >> double operator[](int j) const;

    >
    >
    > It declares that the method does not alter any "non mutable" object state.
    >
    > e.g.
    >
    > struct A {
    > int a;
    > mutable int b;
    > void doer_a() const
    > {
    > a = 3; // illegal;
    > }
    > void doer_b() const
    > {
    > b = 3; // legal;
    > }
    > };
    >
     
    Sim, Aug 24, 2003
    #7
  8. Andre

    Sim Guest

    The topic seemed interesting so I gave it a try myself. I can't get my
    proxy class running. I get a number of errors when I do something like:

    matrixA[0][0] = 5.0;

    or std::cout << matrixA[0][0];

    I simply did a:

    const Proxy operator[](int i) const {
    return this->proxy;
    }

    Proxy operator[](int i) {
    return this->proxy;
    }

    and in proxy I did:

    double operator[](int j) const {
    return matrix->[j];
    }
    double& operator[](int j) {
    return matrix->[j];
    }

    and I had my two-dim array in the proxy class:

    double **matrix;


    What am I doing wrong? Andre if you got it working could you help me out?

    thanks

    Sim


    Immanuel Albrecht wrote:

    > "John Harrison" <> wrote in
    > news:bib1jv$798kd$-berlin.de:
    >
    >
    >>"Andre" <> wrote in message
    >>news:...
    >>
    >>>Hi,
    >>>
    >>>I have a class which contains a two-dimensional array. I need to
    >>>overload something like the [][] operator so that I'm able to access
    >>>the internal array elements via the class object. For example:
    >>>
    >>>Matrix a = new Matrix(10,10);
    >>>
    >>>a[1][1] = 6;
    >>>
    >>>Is this possible? How can I simulate a two dimensional array using a
    >>>class in c++? Thanks
    >>>
    >>>-Andre
    >>>

    >>
    >>There is no operator[][], there is only the operator[]. You can do
    >>what you want with a proxy class, something like this
    >>
    >>class Proxy
    >>{
    >>public:
    >> double operator[](int j) const;

    >
    > const double&
    >
    >> double& operator[](int j);
    >>};
    >>
    >>class Matrix
    >>{
    >>public:
    >> const Proxy operator[](int i) const;

    >
    > ^^^^^
    > const Proxy & and
    >
    >> Proxy operator[](int i);

    >
    > Proxy& will have better performance, plus, you can have the
    > proxyclass save a reference to your data matrix-row and I would make this
    > class inside the Matrix namespace to avoid name collisions with other
    > Proxy classes for different multi-dimensional arrays.
    >
    >>};

    >
    >
    > References combined with inline functions will have improved performance,
    > since there will be no copy-constructor and destructor calls, less
    > overhead.
     
    Sim, Aug 24, 2003
    #8
  9. "Immanuel Albrecht" <> wrote in message
    news:bib6g1$l5c$03$-online.com...
    > "John Harrison" <> wrote in
    > news:bib1jv$798kd$-berlin.de:
    >
    > >
    > > "Andre" <> wrote in message
    > > news:...
    > >> Hi,
    > >>
    > >> I have a class which contains a two-dimensional array. I need to
    > >> overload something like the [][] operator so that I'm able to access
    > >> the internal array elements via the class object. For example:
    > >>
    > >> Matrix a = new Matrix(10,10);
    > >>
    > >> a[1][1] = 6;
    > >>
    > >> Is this possible? How can I simulate a two dimensional array using a
    > >> class in c++? Thanks
    > >>
    > >> -Andre
    > >>

    > >
    > > There is no operator[][], there is only the operator[]. You can do
    > > what you want with a proxy class, something like this
    > >
    > > class Proxy
    > > {
    > > public:
    > > double operator[](int j) const;

    > const double&
    > > double& operator[](int j);
    > > };
    > >
    > > class Matrix
    > > {
    > > public:
    > > const Proxy operator[](int i) const;

    > ^^^^^
    > const Proxy & and
    > > Proxy operator[](int i);

    > Proxy& will have better performance,


    If you return a reference, then you have to have an object to refer to.
    Where do you propose to store that object? I think its well known that this
    scheme is impossible to implement correctly and safely. See for instance
    Effective C++ by Scott Meyer who gives all the various flawed possibilities
    a good going over.

    Unless of course you have some code that shows differently ...

    john
     
    John Harrison, Aug 24, 2003
    #9
  10. "Sim" <> wrote in message
    news:3f49202f$...
    > The topic seemed interesting so I gave it a try myself. I can't get my
    > proxy class running. I get a number of errors when I do something like:
    >
    > matrixA[0][0] = 5.0;
    >
    > or std::cout << matrixA[0][0];
    >
    > I simply did a:
    >
    > const Proxy operator[](int i) const {
    > return this->proxy;
    > }
    >
    > Proxy operator[](int i) {
    > return this->proxy;
    > }
    >
    > and in proxy I did:
    >
    > double operator[](int j) const {
    > return matrix->[j];
    > }
    > double& operator[](int j) {
    > return matrix->[j];
    > }
    >
    > and I had my two-dim array in the proxy class:
    >
    > double **matrix;
    >
    >
    > What am I doing wrong? Andre if you got it working could you help me out?
    >


    Well the two dim array is supposed to be in the Matrix class. The proxy
    class just hold a reference to the matrix and the first index.

    Something like this (untested code)

    class Matrix;

    class Proxy
    {
    friend class Matrix;
    double& operator[](int j) { return m.matrix[j]; }
    private:
    Proxy(Matrix& mm, int ii) : m(mm), i(ii) {}
    Matrix& m;
    int i;
    };

    class Matrix
    {
    friend class Proxy;
    public:
    Proxy operator[](int i) { return Proxy(*this, i); }
    private:
    double** matrix;
    };

    Basically the Proxy class just holds the parameters used in the first
    operator[] call, so that when the second operator[] call happens they are
    available to get the element from the Matrix.

    john

    > thanks
    >
    > Sim
    >
    >
    > Immanuel Albrecht wrote:
    >
    > > "John Harrison" <> wrote in
    > > news:bib1jv$798kd$-berlin.de:
    > >
    > >
    > >>"Andre" <> wrote in message
    > >>news:...
    > >>
    > >>>Hi,
    > >>>
    > >>>I have a class which contains a two-dimensional array. I need to
    > >>>overload something like the [][] operator so that I'm able to access
    > >>>the internal array elements via the class object. For example:
    > >>>
    > >>>Matrix a = new Matrix(10,10);
    > >>>
    > >>>a[1][1] = 6;
    > >>>
    > >>>Is this possible? How can I simulate a two dimensional array using a
    > >>>class in c++? Thanks
    > >>>
    > >>>-Andre
    > >>>
    > >>
    > >>There is no operator[][], there is only the operator[]. You can do
    > >>what you want with a proxy class, something like this
    > >>
    > >>class Proxy
    > >>{
    > >>public:
    > >> double operator[](int j) const;

    > >
    > > const double&
    > >
    > >> double& operator[](int j);
    > >>};
    > >>
    > >>class Matrix
    > >>{
    > >>public:
    > >> const Proxy operator[](int i) const;

    > >
    > > ^^^^^
    > > const Proxy & and
    > >
    > >> Proxy operator[](int i);

    > >
    > > Proxy& will have better performance, plus, you can have the
    > > proxyclass save a reference to your data matrix-row and I would make

    this
    > > class inside the Matrix namespace to avoid name collisions with other
    > > Proxy classes for different multi-dimensional arrays.
    > >
    > >>};

    > >
    > >
    > > References combined with inline functions will have improved

    performance,
    > > since there will be no copy-constructor and destructor calls, less
    > > overhead.

    >
     
    John Harrison, Aug 24, 2003
    #10
  11. >
    > Well the two dim array is supposed to be in the Matrix class. The proxy
    > class just hold a reference to the matrix and the first index.
    >
    > Something like this (untested code)
    >
    > class Matrix;
    >
    > class Proxy
    > {
    > friend class Matrix;
    > double& operator[](int j) { return m.matrix[j]; }
    > private:
    > Proxy(Matrix& mm, int ii) : m(mm), i(ii) {}
    > Matrix& m;
    > int i;
    > };
    >
    > class Matrix
    > {
    > friend class Proxy;
    > public:
    > Proxy operator[](int i) { return Proxy(*this, i); }
    > private:
    > double** matrix;
    > };
    >


    Actually that could be better, in this case all that is needed is for Proxy
    to hold a double*.

    class Matrix;

    class Proxy
    {
    friend class Matrix;
    double& operator[](int j) { return ptr[j]; }
    private:
    Proxy(double* p) : ptr(p) {}
    double* ptr;
    };

    class Matrix
    {
    public:
    Proxy operator[](int i) { return Proxy(matrix); }
    private:
    double** matrix;
    };

    Which I think was what Sim was getting at.

    john
     
    John Harrison, Aug 24, 2003
    #11
  12. On Mon, 25 Aug 2003 04:28:43 +1000, Andre wrote:

    > Hi,
    >
    > I have a class which contains a two-dimensional array. I need to
    > overload something like the [][] operator so that I'm able to access the
    > internal array elements via the class object. For example:
    >
    > Matrix a = new Matrix(10,10);
    >
    > a[1][1] = 6;
    >
    > Is this possible? How can I simulate a two dimensional array using a
    > class in c++? Thanks


    If you don't mind the syntax (some people even like it better), you can
    instead provide an operator() that takes two indexes.

    a(1, 1) = 6;

    It would look something like

    class Matrix {
    // ...
    int& operator()(int row, int col);
    int operator()(int row, int col) const;
    };

    Josh
     
    Josh Sebastian, Aug 25, 2003
    #12
  13. Andre

    John Carson Guest

    "John Harrison" <> wrote in message
    news:bib1jv$798kd$-berlin.de
    > "Andre" <> wrote in message
    > news:...
    > > Hi,
    > >
    > > I have a class which contains a two-dimensional array. I need to
    > > overload something like the [][] operator so that I'm able to
    > > access the internal array elements via the class object. For
    > > example:
    > >
    > > Matrix a = new Matrix(10,10);
    > >
    > > a[1][1] = 6;
    > >
    > > Is this possible? How can I simulate a two dimensional array using a
    > > class in c++? Thanks
    > >
    > > -Andre
    > >

    >
    > There is no operator[][], there is only the operator[]. You can do
    > what you want with a proxy class, something like this
    >
    > class Proxy
    > {
    > public:
    > double operator[](int j) const;
    > double& operator[](int j);
    > };
    >
    > class Matrix
    > {
    > public:
    > const Proxy operator[](int i) const;
    > Proxy operator[](int i);
    > };
    >
    > I hope you get the idea, you overload operator[] on your Matrix
    > object to return another class (the Proxy class), you then overload
    > operator[] on the proxy class to return a Matrix element.
    >
    > john



    There may be good reasons for using a proxy class, but if the matrix is
    stored internally as

    double **matrix;

    as per your later examples, then you can implement a double subscript
    operator by simply having the following in the Matrix class:

    public:
    double * operator[](int i)
    { return matrix; }
    const double * operator[](int i) const
    { return matrix; }

    The built in [] operator will do the rest.


    --
    John Carson
    1. To reply to email address, remove donald
    2. Don't reply to email address (post here instead)
     
    John Carson, Aug 25, 2003
    #13
  14. "John Harrison" <> wrote in
    news:bib7vu$7j6lp$-berlin.de:

    First of all, sorry for being late, I was at vacation...

    > If you return a reference, then you have to have an object to refer
    > to. Where do you propose to store that object?

    Of course, in your Matrix class your object should be stored.
    > I think its well known
    > that this scheme is impossible to implement correctly and safely. See
    > for instance Effective C++ by Scott Meyer who gives all the various
    > flawed possibilities a good going over.


    I'm sorry, but I haven't read this book.
    >
    > Unless of course you have some code that shows differently ...


    So what's wrong with e.g. this:


    #include <iostream>
    #include <ostream>

    #include <vector>

    template <int rows,int cols> class Matrix
    {
    private:
    double mat[rows][cols];
    public:
    class Proxy {
    private:
    Matrix* m;
    int row;

    friend class Matrix;

    void SetRow(int r)
    { row = r;}

    void SetMat(Matrix* matrix)
    { m = matrix;}

    public:
    Proxy() {}

    const double& operator [](int i) const;
    double& operator [](int i);

    };

    friend class Proxy;
    private:
    std::vector<Proxy> prox;

    public:

    Matrix() : prox(rows)
    {
    for (unsigned int r=0;r<rows;r++)
    {
    prox[r].SetRow(r);
    prox[r].SetMat(this);
    }
    }

    const Proxy& operator[] (int i) const
    {
    return prox;
    }

    Proxy& operator[] (int i)
    {
    return prox;
    }

    };

    template <int rows, int cols>
    const double& Matrix<rows,cols>::proxy::eek:perator[](int i) const
    {
    return m->mat[row];
    }

    template <int rows, int cols>
    double& Matrix<rows,cols>::proxy::eek:perator[](int i)
    {
    return m->mat[row];
    }



    int main()
    {
    Matrix<4,4> m;

    for (unsigned int r=0;r<4;r++)
    for (unsigned int c=0;c<4;c++)
    {
    std::cout << r << " " << c <<std::endl;
    m[r][c] = r+c;
    }

    for (unsigned int r=0;r<4;r++)
    {
    for (unsigned int c=0;c<4;c++)
    std::cout << m[r][c] << " ";

    std::cout << std::endl;
    }


    return 0;
    }
     
    Immanuel Albrecht, Aug 30, 2003
    #14
  15. "Immanuel Albrecht" <> wrote in message
    news:biq3ak$4pn$07$-online.com...
    > "John Harrison" <> wrote in
    > news:bib7vu$7j6lp$-berlin.de:
    >
    > First of all, sorry for being late, I was at vacation...
    >
    > > If you return a reference, then you have to have an object to refer
    > > to. Where do you propose to store that object?

    > Of course, in your Matrix class your object should be stored.
    > > I think its well known
    > > that this scheme is impossible to implement correctly and safely. See
    > > for instance Effective C++ by Scott Meyer who gives all the various
    > > flawed possibilities a good going over.

    >
    > I'm sorry, but I haven't read this book.
    > >
    > > Unless of course you have some code that shows differently ...

    >
    > So what's wrong with e.g. this:
    >
    >
    > #include <iostream>
    > #include <ostream>
    >
    > #include <vector>
    >
    > template <int rows,int cols> class Matrix
    > {
    > private:
    > double mat[rows][cols];
    > public:
    > class Proxy {
    > private:
    > Matrix* m;
    > int row;
    >
    > friend class Matrix;
    >
    > void SetRow(int r)
    > { row = r;}
    >
    > void SetMat(Matrix* matrix)
    > { m = matrix;}
    >
    > public:
    > Proxy() {}
    >
    > const double& operator [](int i) const;
    > double& operator [](int i);
    >
    > };
    >
    > friend class Proxy;
    > private:
    > std::vector<Proxy> prox;
    >
    > public:
    >
    > Matrix() : prox(rows)
    > {
    > for (unsigned int r=0;r<rows;r++)
    > {
    > prox[r].SetRow(r);
    > prox[r].SetMat(this);
    > }
    > }
    >
    > const Proxy& operator[] (int i) const
    > {
    > return prox;
    > }
    >
    > Proxy& operator[] (int i)
    > {
    > return prox;
    > }
    >
    > };
    >
    > template <int rows, int cols>
    > const double& Matrix<rows,cols>::proxy::eek:perator[](int i) const
    > {
    > return m->mat[row];
    > }
    >
    > template <int rows, int cols>
    > double& Matrix<rows,cols>::proxy::eek:perator[](int i)
    > {
    > return m->mat[row];
    > }
    >
    >
    >
    > int main()
    > {
    > Matrix<4,4> m;
    >
    > for (unsigned int r=0;r<4;r++)
    > for (unsigned int c=0;c<4;c++)
    > {
    > std::cout << r << " " << c <<std::endl;
    > m[r][c] = r+c;
    > }
    >
    > for (unsigned int r=0;r<4;r++)
    > {
    > for (unsigned int c=0;c<4;c++)
    > std::cout << m[r][c] << " ";
    >
    > std::cout << std::endl;
    > }
    >
    >
    > return 0;
    > }


    Well you've answered my point

    > > If you return a reference, then you have to have an object to refer
    > > to. Where do you propose to store that object?


    by creating a vector of proxys. But that's an overhead for every matrix to
    carry around. Arguably its a small amount of space compared to the matrix as
    a whole. Whether your method is better than copying the Proxy class as I
    suggested would depend on the application I think. In any case, as John
    Carson pointed out, this time the proxy class need only be a pointer, which
    is better than both our methods.

    john
     
    John Harrison, Aug 30, 2003
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Iyer, Prasad C

    Overloading __init__ & Function overloading

    Iyer, Prasad C, Sep 30, 2005, in forum: Python
    Replies:
    3
    Views:
    6,413
    Fredrik Lundh
    Sep 30, 2005
  2. Fredrik Lundh
    Replies:
    0
    Views:
    451
    Fredrik Lundh
    Sep 30, 2005
  3. Steve Holden
    Replies:
    0
    Views:
    431
    Steve Holden
    Sep 30, 2005
  4. Iyer, Prasad C
    Replies:
    4
    Views:
    581
    John J. Lee
    Sep 30, 2005
  5. Fredrik Lundh
    Replies:
    0
    Views:
    402
    Fredrik Lundh
    Sep 30, 2005
Loading...

Share This Page