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

Reply via email to