Re: C-style casts - "does the right thing" for templates?
* Stephen Howe:
http://groups.google.de/group/comp.lang.c++.moderated/browse_thread/thread/c677ee3ed10e5c12/5c203c7ea94d7e0b
However, the thread does mention the alternative C++-style
casts, and it also deals with a topic that deals with
implementation-defined behaviour anyway, AFAIUI (as determining
the address of an object is always inherently non-portable).
May be, but skimming the thread I think it illustrates the opposite of what
Stephen literally asks for, a case where a C style cast may do the wrong thing.
Although it's very strongly related. So, useful (it's also interesting thread!).
Alf:
I think it is this thread. My memory is a trying to dredge up what I read
at least 5 years ago :-) I remember that it was difficult at the time to
get the new-style casts right depending on the template type.
The C-style cast was recommended (John Potter), because most of the time
it did the right thing.
Hm, well, "most of the time".
John Potter wrote then
* John Potter:
I just let the compiler do the right thing with the C style
cast because it must. Bad style because it is not grepable,
but neither is addressof when looking for casts. In my code
(char&)(v) is const_cast<char&>(reinterpret_cast<char const&>(v))
For the case when T is U const.
Does anyone have an example where one form will work and the other
will fail on a conforming compiler?
Apparently nobody replied to that (but Google's archive is unreliable),
presumably because that question had already been covered by Rani Sharoni and
Ulrich Echard, namely, what if T has a defined conversion to 'char&'?
For example,
<code>
#include <stdio.h>
struct T
{
operator char const& () { return "Blah blah"[0]; }
void const* addr() const { return this; }
};
int main()
{
T o;
void const* pWrong = &(char const&)(o);
void const* pRight =
reinterpret_cast< void const* >(
const_cast< char const* > (
&reinterpret_cast< char const volatile& >( o )
)
);
printf( "pWrong is %s\n", (pWrong == o.addr()? "OK" : "wrong" ) );
printf( "pRight is %s\n", (pRight == o.addr()? "OK" : "wrong" ) );
}
</code>
That was 2003, who knows, by now we have improved in knowledge in terms of
template magic (and with C++ 0x waiting in the
wings), perhaps addressof() can be written as a collection of cases with
new-style casts.
Except for the single case that I noted earlier, accessing an inaccesible base,
which is unrelated to the address question, *any* C style cast can be expressed
as combination of named C++ casts, and that's how the standard defines it.
And except for result constness the reinterpret_cast/const_cast combo was how
Boost implemented addressof at that time, as noted in the referenced thread.
AFAIK that's still how Boost still implements it as of 2010.
A C style cast can do one thing that other casts cannot, namely to give you a
pointer to an inaccessible base class subobject.
The two other special casts that I know of are dynamic_cast<void*> to give a
pointer to the most derived object
I was reading Dewhurst 100 Gotcha's and he covered the 4 reasons
dynamic_cast can return NULL.
:-)
Cheers,
- Alf
PS: I tried to wait hoping Someone Else(TM) would make these observations. But
since that didn't happen, I think it's better for you to know. To not go on with
a wrong impression, wrong facts.