powell@ole.UUCP (Gary Powell) (06/06/90)
I am new to C++ but after a seminar and some play time I tried writting a class for two diminsional arrays. What I found myself wanting was a overloaded operator [][](int)(int). However my GNU g++ 1.35 compiler complains bitterly when I tried to code this. Why not use the (int,int) operator? Well I was using that for the initialization. It would seem to me that since C allows array[][] access that C++ should allow overloading of this also. With this background has there been any discussion on the overloading of [][] ....[]? And is this a reasonable extension to the language? Resons for doing this are that N'dim. arrays are a pain to pass to functions. With a class I can add the extra information for bounds checking and pass the arguement as a single pointer and let the compiler call my code to access the array. class TWO_DIM { public: TWO_DIM(int r,int c) { /* initialize */} int & operator[][](int r)(int c) { /* bound check */ return & array [r][c];} ~TWO_DIM() {delete array;} private: int *array, max_col, max_row; }; subroutine (TWO_DIM &i-arry) { i-arry[5][2] = i-arry[2][5]; // garbage code. } main() { TWO_DIM i-array(10,20); i-array[0][15] = 5; subroutine (i-array); } -- _Q _Q _Q _Q _Q_Q _Q _Q _Q /_\) /_\) /_\) /_\)/_/\\) /_\) /_\) Gary Powell /_\) _O|/O_O|/O__O|/O___O|/O_OO|/O__O|/O__O|/O__________________________________O|/O_ uunet!uw-beaver!sumax!ole!powell Seattle Silicon Corp. (206) 828-4422
keith@csli.Stanford.EDU (Keith Nishihara) (06/07/90)
In <1589@ole.UUCP> powell@ole.UUCP (Gary Powell) writes: >[...] What I found myself wanting was >a overloaded operator [][](int)(int). However my GNU g++ 1.35 compiler >complains bitterly when I tried to code this. You can do it in the obvious way using two applications of operator[]. If you want to do checking or other additional functions on both indeces, you will need to define a half way class which is returned from the first application of operator[], and which serves simply as a base for the second operator[]. For example: #include <stdio.h> // Declarations. class A; class Half; // Define class A which is a 2D array. class A { public: A(); Half & operator[] (int); private: friend class Half; int x; int y; int *data; }; // Constructor simply sets up a dummy array and initialises it. A::A() { x = 5; y = 10; data = new int[x * y]; for(int j = 0; j < x * y; j++) data[j] = j; } // Define class Half which is a placeholder for the half decoded array access. class Half { public: int operator[] (int); private: friend class A; int * a; // half decoded access. A * from; // pointer to original array. }; // First half of array access. Half & A::operator[] (int j) { printf("A::operator[%d]\n", j); static Half h; if(j < 0) // Range checking. j = 0; if(j >= y) j = y-1; h.a = data + j*x; // Part access. h.from = this; // So that Half can get to array dimensions. return h; // Return reference to local static Half. } // Second half of array access. int Half::operator[] (int i) { printf("Half::operator[%d]\n", i); if(i < 0) // Range checking. i = 0; if(i >= from->x) i = from->x - 1; return a[i]; // Rest of access. } main() { A array; printf("Normal access: %d\n\n", array[2][3]); printf("Out of bounds in first half: %d\n\n", array[20][3]); printf("Out of bounds in second half: %d\n\n", array[2][30]); } // Gives results: // // A::operator[2] // Half::operator[3] // Normal access: 13 // // A::operator[20] // Half::operator[3] // Out of bounds in first half: 48 // // A::operator[2] // Half::operator[30] // Out of bounds in second half: 14 Neil/. Neil%teleos.com@ai.sri.com
tmb@lem.ai.mit.edu (Thomas M. Breuel) (06/08/90)
In article <1589@ole.UUCP>, powell@ole.UUCP (Gary Powell) writes: |>I am new to C++ but after a seminar and some play time I tried writting |>a class for two diminsional arrays. What I found myself wanting was |>a overloaded operator [][](int)(int). However my GNU g++ 1.35 compiler |>complains bitterly when I tried to code this. Why not use the (int,int) |>operator? Well I was using that for the initialization. It would seem to |>me that since C allows array[][] access that C++ should allow overloading |>of this also. |> |>With this background has there been any discussion on the overloading of |>[][] ....[]? |> |>And is this a reasonable extension to the language? |> |>Resons for doing this are that N'dim. arrays are a pain to pass |>to functions. With a class I can add the extra information for bounds |>checking and pass the arguement as a single pointer and let the compiler |>call my code to access the array. Overloading "operator[][]" is not really the right thing to do-- there is no such thing as an "operator[][]". Probably the best solution is to break with tradition and make "operator[]" completely analogous to "operator()" in the treatment of "multiple arguments" and commas. This would constitute a minor incompatiblity with ANSI C, since ANSI a[1,2] would now have to be written a[(1,2)], but this should not affect a lot of code, and it should be easy to fix where it occurs. An ANSI C compatible solution to the problem would be to treat "operator[]" analogous to "operator()" iff it is used with a non-pointer type. If someone implemented this in GNU C++, I'm sure it would catch on... it is simply a very useful feature. Thomas PS: The popular approach to "overloading operator[][]" is to have the first operator[] return a "partially dereferenced result", and have the second operator[] complete the job: struct floatArray2d = { ... partiallyDereferencedFloatArray2D operator[](int) { ... } }; struct partiallyDereferencedArray2D = { floatArray2D array; int index1; float operator[](int) { ... } }; This is, of course, undesirably complex and messy. Incidentally, the same kludge is used for defining the equivalent of CommonLisp SETF methods, and, again, a simple mechanism would be desirable.
jimad@microsoft.UUCP (Jim ADCOCK) (06/09/90)
In article <1589@ole.UUCP> powell@ole.UUCP (Gary Powell) writes: >I am new to C++ but after a seminar and some play time I tried writting >a class for two diminsional arrays. What I found myself wanting was >a overloaded operator [][](int)(int). However my GNU g++ 1.35 compiler >complains bitterly when I tried to code this. Why not use the (int,int) >operator? Well I was using that for the initialization. It would seem to >me that since C allows array[][] access that C++ should allow overloading >of this also. > >With this background has there been any discussion on the overloading of >[][] ....[]? > >And is this a reasonable extension to the language? No, it shouldn't be necessary, and [][] is not one operator but two. Changing [][] from two operators to one would significantly change C++ from the C past. And doing so shouldn't be necessary. There are two common tricks used by people doing 2-dim [or n-dim] arrays in C++. Examples follow. The first trick is to build up your objects from rows and columns as the two [] operators implies. The second trick is to return a proxy object from the first application of [], that "remembers" where you are in the 2-dim [n-dim] array after the first application, and then the second application of [] is applied to the proxy object, which "remembers" the previous index, and thus has all the information necessary to return the correct element in the 2-dim [n-dim] array. BUT: be forwarned there are a fair amount of C and/or C++ compilers out there that have a hard time correctly compiling the code necessary to do proxies! // Example of building up a two dimemsional array one dimension at a time: extern "C" { #include "stdio.h" } class COL { public: int c[10]; int& operator[](int i) { printf("COL[%d] ",i); return c[i]; } }; class MAT { public: COL r[10]; COL& operator[](int j) { printf("ROW[%d] ",j); return r[j]; } }; main() { MAT mat; mat[5][6] = 56; printf("\n"); mat[6][5] = 65; printf("\n"); printf("mat[5][6] %d\n", mat[5][6]); printf("mat[6][5] %d\n", mat[6][5]); } // example of using proxies: extern "C" { #include "stdio.h" } #include "shortnew.h" typedef int* PI; class PROXY { const PI c; public: PROXY(const PI cc) : c(cc) {} int& operator[](int i) const { printf("COL[%d] ",i); return c[i]; } }; class MAT { int i[100]; public: PROXY operator[](int j) const { printf("ROW[%d] ",i); return &(i[j*10]); } }; main() { MAT mat; mat[5][6] = 56; printf("\n"); mat[6][5] = 65; printf("\n"); printf("mat[5][6] %d\n", mat[5][6]); printf("mat[6][5] %d\n", mat[6][5]); }
diamond@tkou02.enet.dec.com (diamond@tkovoa) (06/11/90)
In article <8903@life.ai.mit.edu> tmb@ai.mit.edu writes: >Overloading "operator[][]" is not really the right thing to do-- >there is no such thing as an "operator[][]". Syntactically, [][] has not been specified as a single operator, but it is possible to do so. (Semantically, it has already been done: char *x[10]; char y[10][20]; Then z = x[5][6]; generates different code from z = y[5][6]; but this could not be done if [][] were really two separate operators.) >Probably the best solution is to break with tradition and >make "operator[]" completely analogous to "operator()" in >the treatment of "multiple arguments" and commas. This would >constitute a minor incompatiblity with ANSI C, since >ANSI a[1,2] would now have to be written a[(1,2)], but >this should not affect a lot of code, and it should be easy >to fix where it occurs. Exactly. A couple of years ago, I pointed out that the existing semantics are already somewhat inconsistent. In function calls and initializers, if one wants the comma operator instead of just a separator, then one has to use an extra set of parentheses. Theoretically, such a change could break existing code. Anyone want to bet that any real, serious code, outside of compiler test suites, really uses the comma operator inside a pair of square brackets? -- Norman Diamond, Nihon DEC diamond@tkou02.enet.dec.com Proposed group comp.networks.load-reduction: send your "yes" vote to /dev/null.