Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!uupsi!sunic!dkuug!diku!juul From: juul@diku.dk (Anders Juul Munch) Newsgroups: comp.lang.c++ Subject: Re: operator[][] ? Keywords: operator[] Message-ID: <1991Jun20.202930.2805@odin.diku.dk> Date: 20 Jun 91 20:29:30 GMT References: <3286@krafla.rhi.hi.is> Sender: juul@skinfaxe.diku.dk Organization: Department of Computer Science, U of Copenhagen Lines: 93 heimir@rhi.hi.is (Heimir Thor Sverrisson) writes: HTS>Hi fellow Netlanders, HTS>is there anyone out there that can help me understand why the following HTS>code works! I'm trying to build a class that contains integer data HTS>that should be organized as a two-dimensional array (of fixed dimensions). HTS>I was trying to implement an operator that would allow me to use code like: HTS> Status st; HTS> st[TOTAL][COD]=123; HTS>where Status is the name of my class and the [][] notation would allow me HTS>to manipulate that element in my private array. On top of the well known HTS>problem of not being able to detect if I'm being used as an l- or r-value HTS>I also ran into trouble defining the operator(s) involved to do this. HTS>What I ended up with were two operator[]'s and the code did actually work HTS>in g++ 1.39. The implementation is : HTS> int* Status::operator[](int index) HTS> { HTS> return stat[index]; // private: int stat[i][j] HTS> } HTS> int& Status::operator[](int* iarr) HTS> { HTS> return *iarr; HTS> } HTS>And I'm asking you why does this work? HTS>If it is not a compiler bug/feature, how can I access the latter index (COD) HTS>from within the second member function above (i.e. to test it's range)? HTS>[Remainder omitted.] What is happening is this: First, 'stat[TOTAL]' is evaluated. This is done by 'Status::operator[](int)', because 'stat' is of class 'Status', and the argument matches. 'Status::operator[](int)' returns an 'int*'. This return value is then indexed by '[COD]'. However, as 'int*' is not a class type, no member function is being called this time. Instead, usual C array referencing is performed. Your second member function, 'Status::operator[](int*)' will never get called! Yes, it works, but this way you have no way to range check the second index. To get control of both indices is pretty hard, if you insist on using operator[]. If you don't, there is no problem, you could define an array access member function like this: int& Status::Stat(int firstIndex, int secondIndex) { // Check if indices are valid here. return stat[firstIndex][secondIndex]; } // The brackets aren't square, but what the heck . . . Status st; st(TOTAL,COD) = 123; If you insist on using operator[], it could be done using an intermediate class: class ArrayRow { int* row; public: ArrayRow(int* it) { row = it; } int& operator[](int secondIndex) { // Check range of secondIndex here. return row[secondIndex]; } }; ArrayRow Status::operator[](int firstIndex) { // Check range of firstIndex here. return ArrayRow(stat[i]); } This should work: You get all the range checking you want, and you can still use the usual []-s. The performance penanlty involved in creating the intermediate 'ArrayRow' object is negliable. - A good compiler might even optimize it away entirely. The cost is that the code gets distributed over two classes in a not very intuitive manner. Indeed, the intermediate class is a trick which would make your code a lot more confusing. -- Anders Munch juul@diku.dk University of Copenhagen Denmark