Я думаю, что это явно не хорошо.
В качестве предисловия и время жизни объекта действительно можно закончить, вызвав деструктор, но вы только можете (и обязаны) создать новый объект вместо него того же типа :
{
Foo x;
x.~Foo();
::new (&x) Foo;
} // x.~Foo() must be a valid call here!
Помните, что в конце области будет вызван деструктор!
Но в вашем случае вы полностью создаете другой объект:
::new (&x) Bar; // Bar = DerivedA<int>
Очевидно, что если sizeof(Bar)
превышает sizeof(Foo)
, это не может быть в порядке.
(Возможно, если вы можете сделать дополнительные гарантии и для размеров объекта, такжечто касается гарантий выравнивания, мы можем подумать об этом дальше.)
Обновление: Даже если вы думаете, хорошо, значит, эти типы получены из одной и той же базы, поэтому вызовемДеструктор приносит виртуальное счастье, я все еще уверен, что это нарушение.В этом статическом параметре компилятор вполне может разрешить виртуальный вызов статически, поэтому вы нарушаете предположения компилятора, если вы изменяете динамический тип объекта, на который указывает &x
.
Обновление 2: Еще одна мысль по тому же вопросу: статический тип из *&x
известен, и я думаю, что вы должны уважать это.Другими словами, у компилятора нет оснований учитывать вероятность того, что статический тип локальной переменной изменится.