1. Свой код — сделать функцию init
Foo foo;
if (someFlag)
foo.init("SomeString");
else foo.init(42);
2. Чужой код — сделать обёртку, которая в init будет использовать placement new, а в деструкторе — явно вызывать деструктор объекта.
class FooWrap {
public:
FooWrap() : hasFoo(false) {}
void init(int x) { new (fooPlace) Foo(x); hasFoo = true; }
Foo& operator * () { return *reinterpret_cast<Foo*>(fooPlace); }
Foo* operator -> () { return reinterpret_cast<Foo*>(fooPlace); }
~FooWrap() { if (hasFoo) (*this)->~Foo(); }
// Да, и конструктор копирования и op= не забыть — оставлю как упражнение.
private:
char fooPlace[sizeof(Foo)];
bool hasFoo;
}
FooWrap foo;
if (someFlag)
foo.init("SomeString");
else foo.init(42);
foo->doFoo();
Для большей надёжности стоит указать, что FooWrap выравнивать как Foo — это делается через C++11 или расширениями компилятора.