The real answer has nothing to do with an implicit call to operator LPCTSTR (), and I think it's kind of clever how it actually works.
To implement a string class, you need the string's data buffer, of course, as well as some other data fields, like the length of the string, maybe how much memory is allocated, maybe a reference count, etc.
But how would you make variadic functions see a C-style string when passing a CString argument? You could put the data buffer field (a pointer to char*) as the first member, but then all the other fields (like string length) also get unexpectedly pushed onto the stack as if they were extra function arguments.
So the next thing you try is to package all of the fields into a single memory structure which is allocated along with the string'd character data buffer. And if this data buffer is located at the start of the aggregate structure, a variadic function expecting a C-string will see the beginning of this structure. If a terminal null is placed at the end of the data buffer, before the other data fields, then printf will stop reading string data before it hits the data you don't want it to see and everything works out fine!
But then you realize you have a new problem -- the length of the character data buffer is variable, and the "length" field is now located in memory after the character data, so you would need to know "length" in order to know where the "length" field can be found.
So can you move "length" and all the other extra fields to the beginnning of the structure, in memory before the character data? Of course not, printf would now see some funny characters (or even a null) added at the beginning of the real string.
But this is what CString does. However, its single member variable is a pointer, not to the start of the aggregate struct, but to the memory location inside it where the character data begins.
And because the data fields (without the character buffer) have a fixed size, the string class knows how to access them in memory, given its pointer to char (these fields are located at a negative offset from the pointer to char). And of course, when it frees its aggregate structure, the class will also need to calculate where its original memory allcation begins, not just use its pointer to char.
operator LPCTSTRoverloaded. - Algirdas Preidžiusprintfand Clang actually gives an error (at least in my example case). Actually, I found a case withCStringthat VS2015 complains about. - chrisCStringin a huge project? It's still there, after decades, simply because it works. It implements conversion between MBCS and Unicode, plays well with C-style arguments, and sports COM support. - IInspectable