overloading [][]

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andre

    overloading [][]

    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

  • John Harrison

    #2
    Re: overloading [][]


    "Andre" <food_crazy@hot mail.com> wrote in message
    news:3f4900eb@c larion.carno.ne t.au...[color=blue]
    > 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
    >[/color]

    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


    Comment

    • Andre

      #3
      Re: overloading [][]

      Neat :) thatnks, I get the idea.

      cheers

      -Andre

      John Harrison wrote:
      [color=blue]
      > "Andre" <food_crazy@hot mail.com> wrote in message
      > news:3f4900eb@c larion.carno.ne t.au...
      >[color=green]
      >>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
      >>[/color]
      >
      >
      > 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
      >
      >[/color]

      Comment

      • Sim

        #4
        Re: overloading [][]

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

        double operator[](int j) const;

        Thanks

        Sim


        John Harrison wrote:
        [color=blue]
        > "Andre" <food_crazy@hot mail.com> wrote in message
        > news:3f4900eb@c larion.carno.ne t.au...
        >[color=green]
        >>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
        >>[/color]
        >
        >
        > 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
        >
        >[/color]

        Comment

        • John Harrison

          #5
          Re: overloading [][]


          "Sim" <simba@no.com > wrote in message
          news:3f49163f$1 @clarion.carno. net.au...[color=blue]
          > Just wondering.. what does they "const" in front of a function do:
          >
          > double operator[](int j) const;
          >
          > Thanks
          >
          > Sim
          >[/color]

          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


          Comment

          • Immanuel Albrecht

            #6
            Re: overloading [][]

            "John Harrison" <john_andronicu s@hotmail.com> wrote in
            news:bib1jv$798 kd$1@ID-196037.news.uni-berlin.de:
            [color=blue]
            >
            > "Andre" <food_crazy@hot mail.com> wrote in message
            > news:3f4900eb@c larion.carno.ne t.au...[color=green]
            >> 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
            >>[/color]
            >
            > 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;[/color]
            const double&[color=blue]
            > double& operator[](int j);
            > };
            >
            > class Matrix
            > {
            > public:
            > const Proxy operator[](int i) const;[/color]
            ^^^^^
            const Proxy & and[color=blue]
            > Proxy operator[](int i);[/color]
            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.[color=blue]
            > };[/color]

            References combined with inline functions will have improved performance,
            since there will be no copy-constructor and destructor calls, less
            overhead.

            Comment

            • Sim

              #7
              Re: overloading [][]

              Thanks. That clears it :-)

              Sim

              Gianni Mariani wrote:[color=blue]
              > Sim wrote:
              >[color=green]
              >> Just wondering.. what does they "const" in front of a function do:
              >>
              >> double operator[](int j) const;[/color]
              >
              >
              > 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;
              > }
              > };
              >[/color]

              Comment

              • Sim

                #8
                Re: overloading [][]

                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[i];
                }

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

                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:
                [color=blue]
                > "John Harrison" <john_andronicu s@hotmail.com> wrote in
                > news:bib1jv$798 kd$1@ID-196037.news.uni-berlin.de:
                >
                >[color=green]
                >>"Andre" <food_crazy@hot mail.com> wrote in message
                >>news:3f4900eb @clarion.carno. net.au...
                >>[color=darkred]
                >>>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
                >>>[/color]
                >>
                >>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;[/color]
                >
                > const double&
                >[color=green]
                >> double& operator[](int j);
                >>};
                >>
                >>class Matrix
                >>{
                >>public:
                >> const Proxy operator[](int i) const;[/color]
                >
                > ^^^^^
                > const Proxy & and
                >[color=green]
                >> Proxy operator[](int i);[/color]
                >
                > 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.
                >[color=green]
                >>};[/color]
                >
                >
                > References combined with inline functions will have improved performance,
                > since there will be no copy-constructor and destructor calls, less
                > overhead.[/color]

                Comment

                • John Harrison

                  #9
                  Re: overloading [][]


                  "Immanuel Albrecht" <xrxixpx@gmx.de > wrote in message
                  news:bib6g1$l5c $03$2@news.t-online.com...[color=blue]
                  > "John Harrison" <john_andronicu s@hotmail.com> wrote in
                  > news:bib1jv$798 kd$1@ID-196037.news.uni-berlin.de:
                  >[color=green]
                  > >
                  > > "Andre" <food_crazy@hot mail.com> wrote in message
                  > > news:3f4900eb@c larion.carno.ne t.au...[color=darkred]
                  > >> 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
                  > >>[/color]
                  > >
                  > > 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;[/color]
                  > const double&[color=green]
                  > > double& operator[](int j);
                  > > };
                  > >
                  > > class Matrix
                  > > {
                  > > public:
                  > > const Proxy operator[](int i) const;[/color]
                  > ^^^^^
                  > const Proxy & and[color=green]
                  > > Proxy operator[](int i);[/color]
                  > Proxy& will have better performance,[/color]

                  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


                  Comment

                  • John Harrison

                    #10
                    Re: overloading [][]


                    "Sim" <simba@no.com > wrote in message
                    news:3f49202f$1 @clarion.carno. net.au...[color=blue]
                    > 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[i];
                    > }
                    >
                    > Proxy operator[](int i) {
                    > return this->proxy[i];
                    > }
                    >
                    > 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?
                    >[/color]

                    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[i][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
                    [color=blue]
                    > thanks
                    >
                    > Sim
                    >
                    >
                    > Immanuel Albrecht wrote:
                    >[color=green]
                    > > "John Harrison" <john_andronicu s@hotmail.com> wrote in
                    > > news:bib1jv$798 kd$1@ID-196037.news.uni-berlin.de:
                    > >
                    > >[color=darkred]
                    > >>"Andre" <food_crazy@hot mail.com> wrote in message
                    > >>news:3f4900eb @clarion.carno. net.au...
                    > >>
                    > >>>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;[/color]
                    > >
                    > > const double&
                    > >[color=darkred]
                    > >> double& operator[](int j);
                    > >>};
                    > >>
                    > >>class Matrix
                    > >>{
                    > >>public:
                    > >> const Proxy operator[](int i) const;[/color]
                    > >
                    > > ^^^^^
                    > > const Proxy & and
                    > >[color=darkred]
                    > >> Proxy operator[](int i);[/color]
                    > >
                    > > Proxy& will have better performance, plus, you can have the
                    > > proxyclass save a reference to your data matrix-row and I would make[/color][/color]
                    this[color=blue][color=green]
                    > > class inside the Matrix namespace to avoid name collisions with other
                    > > Proxy classes for different multi-dimensional arrays.
                    > >[color=darkred]
                    > >>};[/color]
                    > >
                    > >
                    > > References combined with inline functions will have improved[/color][/color]
                    performance,[color=blue][color=green]
                    > > since there will be no copy-constructor and destructor calls, less
                    > > overhead.[/color]
                    >[/color]


                    Comment

                    • Immanuel Albrecht

                      #11
                      Re: overloading [][]

                      "John Harrison" <john_andronicu s@hotmail.com> wrote in
                      news:bib7vu$7j6 lp$1@ID-196037.news.uni-berlin.de:

                      First of all, sorry for being late, I was at vacation...
                      [color=blue]
                      > If you return a reference, then you have to have an object to refer
                      > to. Where do you propose to store that object?[/color]
                      Of course, in your Matrix class your object should be stored.[color=blue]
                      > 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.[/color]

                      I'm sorry, but I haven't read this book.[color=blue]
                      >
                      > Unless of course you have some code that shows differently ...[/color]

                      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<Pro xy> 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[i];
                      }

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

                      };

                      template <int rows, int cols>
                      const double& Matrix<rows,col s>::Proxy::oper ator[](int i) const
                      {
                      return m->mat[row][i];
                      }

                      template <int rows, int cols>
                      double& Matrix<rows,col s>::Proxy::oper ator[](int i)
                      {
                      return m->mat[row][i];
                      }



                      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;
                      }

                      Comment

                      • John Harrison

                        #12
                        Re: overloading [][]


                        "Immanuel Albrecht" <xrxixpx@gmx.de > wrote in message
                        news:biq3ak$4pn $07$1@news.t-online.com...[color=blue]
                        > "John Harrison" <john_andronicu s@hotmail.com> wrote in
                        > news:bib7vu$7j6 lp$1@ID-196037.news.uni-berlin.de:
                        >
                        > First of all, sorry for being late, I was at vacation...
                        >[color=green]
                        > > If you return a reference, then you have to have an object to refer
                        > > to. Where do you propose to store that object?[/color]
                        > Of course, in your Matrix class your object should be stored.[color=green]
                        > > 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.[/color]
                        >
                        > I'm sorry, but I haven't read this book.[color=green]
                        > >
                        > > Unless of course you have some code that shows differently ...[/color]
                        >
                        > 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<Pro xy> 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[i];
                        > }
                        >
                        > Proxy& operator[] (int i)
                        > {
                        > return prox[i];
                        > }
                        >
                        > };
                        >
                        > template <int rows, int cols>
                        > const double& Matrix<rows,col s>::Proxy::oper ator[](int i) const
                        > {
                        > return m->mat[row][i];
                        > }
                        >
                        > template <int rows, int cols>
                        > double& Matrix<rows,col s>::Proxy::oper ator[](int i)
                        > {
                        > return m->mat[row][i];
                        > }
                        >
                        >
                        >
                        > 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;
                        > }[/color]

                        Well you've answered my point
                        [color=blue][color=green]
                        > > If you return a reference, then you have to have an object to refer
                        > > to. Where do you propose to store that object?[/color][/color]

                        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


                        Comment

                        Working...