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?
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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!
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.
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.
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. :-)