Gabriel Dos Reis writes: > "Peter Dimov" <[EMAIL PROTECTED]> writes: > > | From: "Gabriel Dos Reis" <[EMAIL PROTECTED]> > | > David Abrahams <[EMAIL PROTECTED]> writes: > | > > | > | Gabriel Dos Reis <[EMAIL PROTECTED]> writes: > | > | > | > | > Hmm, I have a couple of questions answers to which will help me > | > | > get your point. > | > | > > | > | > 1) Why can't you do that with reinterpret_cast? > | > | > | > | You can, but the results are non-portable > | > > | > No more non-portable than with dangerous_cast<>. > | > | I think that Dave's point is that in > | > | new(h.storage) Foo; > | > | there is a char* -> void* implicit conversion as placement new takes a > | void*. So the placement new performs char* -> void* -> Foo* (by constructing > | a Foo at (void*)h.storage), which - in theory - might not be the same as > | char* -> Foo*. > > But then, that theoretical implementation can remember the type from > which the conversion to void* was made and may issue an error when an > attempt is made to dereference the pointer obtained by recasting the > result of static_cast<void*>(h.storage) to Foo*. > > Practical notes: > Historically, char* was used as the type of "raw memory" until "void*" > was invented. And since then char* and void* continues to have the > same properties as raw-memory issues are concerned.
unsigned char* has _additional_ properties to void* --- you can access the object representation of _any_ object through an unsigned char* (and for PODs, you can copy them around using this) 3.9p4: "The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T)." 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. Also, 3.9.2p4 says: "Objects of cvqualified (3.9.3) or cvunqualified type void* (pointer to void), can be used to point to objects of unknown type. A void* shall be able to hold any object pointer. A cvqualified or cvunqualified (3.9.3) void* shall have the same representation and alignment requirements as a cvqualified or cvunqualified char*." So casting a void* to/from a char* is a no-op. 3.8p1: "The lifetime of an object is a runtime property of the object. The lifetime of an object of type T begins when: - storage with the proper alignment and size for type T is obtained, and - if T is a class type with a nontrivial constructor (12.1), the constructor call has completed." Thus, given that h.storage is properly aligned, (which is the purpose of the other union member), after "new(h.storage) Foo", h.storage contains a Foo object. Thus accessing it through a pointer-to-Foo is legal, as Foo is the dynamic type of the object. The question is: is the Foo* returned by the placement new expression (which is usable) the same as the Foo* returned from static_cast<Foo*>(static_cast<void*>(h.storage))? The object representation of the Foo object is the sizeof(T) bytes starting at static_cast<void*>(h.storage) (since that is what was passed to placement new), so static_cast<void*>(pfoo)==static_cast<void*>(h.storage) if pfoo is the value returned from the new expression. Thus static_cast<Foo*>(static_cast<void*>(pfoo)) ==static_cast<Foo*>(static_cast<void*>(h.storage)) ==pfoo and we're legal. 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