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