unique_ptr to a derived class as an argument to a function that takes a unique_ptr to a base class
You have three options:
Give up ownership. This will leave your local variable without access to the dynamic object after the function call; the object has been transferred to the callee:
f(std::move(derived));
Change the signature of
f
:void f(std::unique_ptr<Derived> const &);
Change the type of your variable:
std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived);
Or of course just:
std::unique_ptr<base> derived(new Derived);
Or even:
std::unique_ptr<base> derived = std::make_unique<Derived>();
Update: Or, as recommended in the comments, don't transfer ownership at all:
void f(Base & b); f(*derived);
I had option #1 of the accepted answer and I still had the same compile error. I banged my head on the wall for over an hour and I finally realized that I had
class Derived : Base {};
instead of
class Derived : public Base {};
A possibile solution is to change the type of the argument to be a Base const*
, and pass derived.get()
instead. There is no transfer of ownership with unique_ptr const<Base>&
(and the unique_ptr
is not being modified), so changing to a Base const*
does not change the meaning.
Herb Sutter discusses passing smart pointer arguments at length in Smart Pointer Parameters. An extract from the linked article refers to this exact situation:
Passing a
const unique_ptr<widget>&
is strange because it can accept only eithernull
or awidget
whose lifetime happens to be managed in the calling code via aunique_ptr
, and the callee generally shouldn’t care about the caller’s lifetime management choice. Passingwidget*
covers a strict superset of these cases and can accept “null
or awidget
” regardless of the lifetime policy the caller happens to be using.