Xref: utzoo comp.lang.c++:12079 comp.std.c++:702 Path: utzoo!news-server.csri.toronto.edu!cs.utexas.edu!uunet!comp.vuw.ac.nz!am.dsir.govt.nz!robert From: robert@am.dsir.govt.nz (Robert Davies) Newsgroups: comp.lang.c++,comp.std.c++ Subject: Re: distinguishing operator[] on left and right Message-ID: <1991Mar7.062634.7598@am.dsir.govt.nz> Date: 7 Mar 91 06:26:34 GMT References: <1991Feb28.212419.20920@ndl.com> <1991Mar2.000705.3496@mathcs.sjsu.edu> <1991Mar2.212017.13885@world.std.com> Organization: DSIR Applied Mathematics, Wellington, NZ Lines: 92 Distinguishing lvalues and rvalues and delayed copy. I posted a note suggesting that Greg Gilley's problem could be resolved if C++ handled constant member functions slightly differently. The problem is to decide whether you need to do a copy when you access an element of a string or vector in a delayed copy situation. See for example the string class in Tony Hansen's book. A couple of people replied. The answers didn't make a lot of sense so I wonder if my item got damaged in transmission. I repeat the problem posed by Greg Gilley. If you have a string class (for example) with delayed copy how do you tell it to copy, if necessary, when you have a statement like String g = f; .... g[3] = 'a'; so that g gets changed but not f (both get changed if you use the code in Tony Hansen's book). But you don't want to copy when you have String g = f; .... char c = g[3]; I suggested having two versions of the operator[] char &operator[](int i) { if (p->refcount > 1) disconnect(); // do the delayed copy now return str()[i]; // get the ref to the element } char operator[](int i) const // constant member function // ARM 9.3.1 { return str()[i]; // get the element } Currently (in Turbo C++ or Sun C++) you need to write char c = ((const String)g)[3]; to get the second version. Which is a bit messy. And the Sun version makes an extra copy of g. I suggest that it would be reasonable for the second version to be the default if the compiler can tell that the operation won't affect the value of g. The line char c = g[3]; will not affect g and the compiler knows this, since in this case the = is predefined. If it is a user defined = then it will depend on whether the = has its argument declared const. Assume it has. Now suppose there are the two versions of operator[] defined in class String: char& operator[](int); and char operator[](int) const; The second version is guaranteed not to affect g. So either version of operator[] is OK. The compilers I have access to choose the first version in c = g[3] (unless g is declared const). They could equally well have used the second version. In other words there would be no damage if the compiler had decided that g had been declared constant. So I suggest, if there are both a const member function and an ordinary member function defined, then the compiler should pretend that the object (g in our case) has been declared "const" and choose the const member version of the function if this compiles OK. This will ensure that the statement char c = g[3]; will get the version of operator[] that doesn't cause a copy. On the other hand g[3] = 'a'; is not allowed if g is const so the compiler must choose the ordinary member function version of operator [].