Gabriel Dos Reis writes:
 > Anthony Williams <[EMAIL PROTECTED]> writes:
 > 
 > |  > Anthony Williams <[EMAIL PROTECTED]> writes:
 > |  > 
 > |  > [...]
 > |  > 
 > |  > | 3.10p15:
 > |  > |   "If a program attempts to access the stored value of an object through an
 > |  > |   lvalue of other than one of the following types the behavior is undefined:
 > |  > | 
 > |  > |   - the dynamic type of the object,
 > |  > | 
 > |  > |   ...
 > |  > | 
 > |  > |   - a char or unsigned char type."
 > |  > | 
 > |  > | So given a Foo object foo, static_cast<char*>(static_cast<void*>(&foo)) is
 > |  > | legal, and can be used to access the object representation of the object.
 > |  > 
 > |  > There is no question that the above cast is legal.  I thin the issue
 > |  > is elsewhere.  The key question is whether that may be different from
 > |  > 
 > |  >    reinterpret_cast<void*>(&foo);
 > | 
 > | I thought the issue was whether the pair of static_cast<>s in dangerous_cast<>
 > | was as implementation defined as a reintepret_cast<> would be. If you read my
 > | mail to the end, hopefully I have explained that I think that the
 > | static_cast<> pair is legal and well-defined, as opposed to using
 > | reinterpret_cast, which is implementation-defined. If I haven't made myself
 > | clear, I apologise, and will try again.
 > 
 > You made youself clear.
 > 
 > However, there are two running issues originating from a claim of Dave
 > that dangerous_cast<> might be better than reinterpret_cast<> in
 > casting from U* to T* (dangerous_cast<> uses the intermediate step
 > void* via static_cast<>).
 > 
 >   1) is dangerous_cast<> better than reinterpret_cast<>?
 > 
 >   2) is it well-defined to dereference the value obtained from
 > 
 >        U* -> void* -> T*
 >     
 >      ?
 > 
 > You've showed that si U == char, (the case in Dave's example) then it
 > is well-formed.  The other cases are left undefined.
 > 
 > So the key question (1) is still unanswered.

Well, given that we have a valid use when U==(unsigned) char, I think it is
certainly better than reinterpret_cast<> in that case.

However, for (2), it is only safe to dereference the resulting pointer if
there is a T at the location that the final T* points to. This is true
irrespective of what U is. However, there are very few cases in which you are
guaranteed to be able to get a valid U* that holds a valid T* --- given that U
and T may have different alignment requirements, and an implementation is
permitted to drop any unnecessary info from pointers, so T* and U* may only
store addresses which are valid multiples of the alignment for T and U
respectively, so it is unlikely that you would get a valid case, unless there
was special dispensation.

One of these is U==char or void, as I showed.

Another case to consider is when U is a POD-struct and T is the type of the
first data member (or vice-versa). In this case, reinterpret_cast<> is
guaranteed to work (9.2p17), so what about dangerous_cast<>? IMO, there is no
guarantee, though I would be surprised if it didn't work. Indeed, I read the
note on that paragraph to indicate that the intent is that the address is the
same, and thus static_cast<void*> will yield the same result. However, I can't
find any normative guarantee.

A third case to consider is when T and U are the types of members of the same
union. In this case, reinterpret_cast<> to a pointer to the union type and
back is guaranteed (since the members are to be allocated as if they were the
only member of a struct), and I would be surprised if it didn't work, but I
can't find a normative guarantee.

If these last two cases are guaranteed to be OK, then I think we have
sufficient to indicate that dangerous_cast<> can be useful. If not, then it
ought to be renamed, and only defined for char types.

Anthony
-- 
Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to