Link to home
Start Free TrialLog in
Avatar of uric
uric

asked on

non const operator[] called by VC6 in rvalue context

I tried to implement ref-counted string with copy-on-write class in C++ using VC6. I wrote:
class String {
// ...
      char& operator[](int index) { copy_on_write(); return m[index]; }
      char operator[](int index) const { return m[index]; }
};

... and expected that:
String s("Hello");
char a=s[0]; // rvalue, should call const method
s[0]=a; // lvalue, calls non-const method and do copy-on-write

But on both cases the non-const verstion was called, hence rendering my copy-on-write mechanism useless.
My question: Did I do some mistake? Shouldn't the const operator[] be called in rvalue context? Or is it a known VC6 issue / BUG? Where is it dosumented?
ASKER CERTIFIED SOLUTION
Avatar of bcladd
bcladd

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mdlilly
mdlilly

How would your compiler know that in the first use of s.operator[](0) you want it to treat s as a constant object?  You didn't tell it that s was a constant object, and since there is a non-const version of operator[] it will naturally invoke the non-const version.

However is you told it specifically to treat s as a constant object it would be more than willing to comply and invoke the const version of operator[].

Example:
const String s("Hello");
char a = s[0]; //invokes the const version of operator[]
s[0] = a; //error you now are trying to invoke the non-const method of a constant object.

Alternately you could just try and "trick" the compiler by saying:
String s("Hello");
char a = (*const_cast<const String*>(&s))[0]; //trick the compiler into thinking s is constant
s[0] = a;

This is NOT a bug with the compiler it is doing EXACTLY what you are telling it to do, you may not however realize what your are telling it to do. :-)
Avatar of uric

ASKER

Well, there IS some kind of misunderstanding:
I really followed the steps of Scott Meyers in "More Effective C++", item 29 (the code is in http://www.aristeia.com/BookErrata/M29Source_frames.html, look for operator[]) in the implementing a string with copy-on-write semantics. Is mr. Meyers wrong?

Thanks again!
Is this the example you are referring to:
void testRCPtr()
{
  String s1 = "String with no changes.";
  String s2(s1);
 
  s2[12] = s2[13] = ' ';
 
  std::cout << s1 << '\n';      // prints "String with no changes."
  std::cout << s2 << '\n';      // prints "String with    changes."
}

in this s2 is NOT a constant object so it calls the non-constant operator[].  Obviously s2 in this example is the lvalue, while in your example s is the rvalue, but the compiler doesn't care if you are the r or l value, but rather if the object being manipulated is a constant object or not.  Now of course if the object is const then the compiler won't let you call any non-const methods but if your object is non-const AND there exists a suitable non-const method then the non-const method will always be called.

Meyer's didn't make an error, neither did the compiler.  Constant objects will only have constant methods called, non-constant objects will prefer to have non-constant methods called but will settle for a constant one when no suitable non-constant one is available.