I have written MyString and MyStringConst class. Now I need from time to time pass MyString as MyStringConst, hence overload cast operator. I have written this
MyString::operator const MyStringConst &() const
{
return reinterpret_cast<const MyStringConst &>(*this);
}
MyString has this data
char * str;
int length;
volatile int hashCode;
int bufferSize;
MyStringConst has this data
const char * c_str;
int length;
volatile int hashCode;
Plus there are some methods, that in both strings can recalculate hashCode.
Is this code correctly written. I have tested it on MSVC 2013 and it is working correctly, but I have no idea if it can be used in production code, that can be compiled with different compiler.
The common initial sequence of the data member is different and C++ makes no guarantee at all about the layout in this case, even if the types differ only by const
qualification. Otherwise the guarantees for union
s would effectively imply that the types need to have a common layout if they are standard-layout types (according to a note in 9.5 [class.union] paragraph 1).
In practice I would expect that the two types are laid out identical and that the reinterpret_cast
works but there is no guarantee by the standard. Based on your comment MyStringConst
merely holds a pointer to the string, i.e., instead of converting to references, I would just return a suitably constructed MyStringConst
and avoid relying on undefined behavior:
MyString::operator MyStringConst() const {
return MyStringConst(str, length);
}
The MyString
object still has to live as long as the result from the conversion but this is no different to the case using reinterpret_cast
.
BTW, the volatile
on the hashCode
is ill-advised: the only effect it will have is to slow down the program. I guess you are trying to use it to achieve synchronization between threads but in C++ volatile
doesn't help with that at all: you get a data race when writing the member in one thread it is also accessed unsynchronized in another thread. You'd spell the member
std::atomic<int> hashCode;
instead.