I learned C++ in the 1990s, but haven't used it much since then. I'm trying to catch up on the last couple of decades by using modern techniques in a small library I maintain at work. I've come across this stylistic question, and I'd like to know what modern consensus is.
I have a pure virtual base class Base
, with two implementations A
and B
. The implementations are not in the header file; their public API is entirely part of Base
. I have factory functions to construct them, which need to call a common initializer. These classes don't support copying, and can change owners during their lifetime, so I use a unique_ptr
to keep things more sane.
In combination, that leads to a somewhat awkward construct:
unique_ptr<Base> rv = make_unique<A>();
I haven't seen cases where make_unique
is explicitly given a template class. I also haven't seen cases where make_unique
can't be used with auto
. However, if I want RVO to apply, then rv
(AFAICT) needs to have type unique_ptr<Base>
rather than unique_ptr<A>
.
Here, I have two deviations from "what I've seen before" in one line. That set off flags in my head, and made me think that I should ask the community for collective wisdom.
Ok, enough English; here's some code:
class Base {
public:
static std::unique_ptr<Base> MakeA();
static std::unique_ptr<Base> MakeB();
private:
void Initialize();
};
class A : public Base {};
class B : public Base {};
std::unique_ptr<Base> Base::MakeA() {
std::unique_ptr<Base> rv = std::make_unique<A>();
rv->Initialize();
return rv;
}
std::unique_ptr<Base> Base::MakeB() {
std::unique_ptr<Base> rv = std::make_unique<B>();
rv->Initialize();
return rv;
}
Again, here's some constraints I'm adding for myself to keep things super-clean:
- Since the classes
A
andB
are implementation details, I don't make them visible externally. - As a consequence, the factory functions need to return a
unique_ptr<Base>
rather thanunique_ptr<A>
andunique_ptr<B>
. - I'm trying to make this NRVO-friendly, since I have other move-only classes to deal with and want to practice making RVO-friendly functions.
- Since the factory functions have to call the
Initialize
method, I have to return an lvalue. - I want to use
make_unique
instead ofunique_ptr(new ...)
, for the usual reasons.
What's the usual way to construct this sort of thing?