I suppose I'm going to get thoroughly trashed for that (read till the end before going all fuming) but... assuming the constructor of windows never throws:
void MyClass::init()
{
obj::~Window(); // destroy the object
new (&obj) Window(...); // construct the object
};
I shall of course underline the not throw requirement of the constructor as if it throws you'll be left with a very muddy situation: the destructor of MyClass
will call the destructor of Window
regardless of whether or not the object is alive and kicking or trashed because of a failed construction, and in the latter case you get undefined behavior.
Of course, a typical thing will thus be std::unique_ptr<Window>
but we have the hurdle of dynamic allocation where clearly the situation does not mandate it...
So you'd be better off using a library: Boost.Optional.
class MyClass
{
public:
private:
boost::optional<Window> obj;
};
The syntax invocation is similar to a pointer:
obj->foo();
But the one benefit is that you get inplace destruction / construction with safer semantics. Destruction is easy:
// both call ~Window() if an instance had been constructed
obj.reset();
obj = detail::none_t();
For construction use a TypedInPlaceFactory. And for assignment too... which of course clears up the previous instance (if any) first:
void MyClass::init(Arg1 arg1, Arg2 arg2)
{
obj = boost::in_place<Window>(arg1, arg2);
}
The main advantage is that if any exception is now encountered during construction, the optional
object is left in the unitialized
state, which is perfectly viable, and thus you need not fear undefined behavior.
So basically it's like having a dynamically allocated object owned by a smart pointer... except that the magic is that the object is not dynamically allocated, thus guaranteeing the very same performances that a "normal" object :)
I should add that the non-copyable hurdle is one of the reason behind the InPlaceFactory creation.