On Tue, Jul 22, 2014 at 3:54 PM, Jan Hubicka <hubi...@ucw.cz> wrote: >> >> As discussen during the Cauldron keeping some builtin doesn't help because >> you are not forced to access the newly created object via the pointer >> returned >> by the placement new. That is, >> >> template <T> >> struct Storage { >> char x[sizeof(T)]; >> Storage() { new (x) T; } >> T& get() { return reinterpret_cast <T&> (x); } >> }; > > This indeed looks like sensible use of placement new... >> >> is valid (and used in this way in Boost - with a type different from 'char' >> to force bigger alignment). > > This testcase with char replaced to long or other POD type is still fine for > my analysis. > I would like to assume that once a polymorphic type is built at a given > location, it can > not be changed to other, that is: > > template <T> > struct Storage { > Q x; > Storage() { new (x) T; } > T& get() { return reinterpret_cast <T&> (x); } > }; > > Where both T and Q are polymorphic types. I think essentially aliasing rules > disallows this (for Q and T being different types at least, not sure if one > inherits other) because Q gets constructed and thus accessed. But it is > sliperly > indeed, as whole concept of placement new. > > I believe easiest way to go forward is to extend polymorphic_call_context to > also hold speculative information about outer type. In the cases I can detect > a dynamic type but can not prove it did not changed, I still can use the > speculative path. This is not perfect, but will improve code quality. > > I am still hoping we can get sensible rules for placement new :)
I don't see why long x[1024]; Q *q = new (x) Q; q->~Q (); new (x) T; would be invalid. I also don't see why Q q; q.~Q (); new (&q) T; would be. Object lifetime is precisely specified and I don't see where it is tied to (static) storage lifetime. Richard. > Honza