Consider this class:
class Widget
{
Widget::Widget();
bool initialize();
}
A Widget
has the following characteristics:
initialize()
must be invoked to fully constructinitialize()
may failinitialize()
is expensiveGiven that, I am encapsulating creation in factory function that always returns the same Widget
instance:
Widget* widget() {
static auto w = new Widget;
static auto initialized = false;
if (!initialized) {
if (!w->initialize()) {
return nullptr;
}
initialized = true;
}
return w;
}
What should the return type of widget()
be?
In particular, I'd like to somehow make it clear that the lifetime of the returned Widget
will outlast any caller, but without referencing the internal implementation.
std::shared_ptr<Widget>
. This is self-documenting, but I don't like that it will introduce completely unnecessary reference counting overhead.std::unique_ptr<Widget>
with a custom deleter function that is a no-op. I think this has the same perceived problem as #2 if the caller converts it into a shared_ptr
.I vote for:
boost::optional<Widget&> widget() {
static Widget w; // no reason for this to be a pointer
static bool initialized = false;
if (!initialized) {
if (!w.initialize()) {
return boost::none;
}
initialized = true;
}
return w;
}
It makes it clear that the caller doesn't own the Widget
in any way, there's no worry of the caller delete
-ing the Widget
, and it's clear whether or not the call succeeded.
Isn't a raw pointer the right thing to do here? It expresses the restrictions already. It can fail (by returning nullptr), and since it makes no promises about the pointer, callers can't safely cause it to be deleted. You're getting a raw pointer, you can't make the assumption that you're allowed to make any statements about the lifetime of the pointed-to object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With