Reputation: 1261
Consider the following simple code:
#include <memory>
template<typename T>
struct Foo
{
virtual T & foo() = 0;
};
struct Bar : public Foo<int>
{
int x;
virtual int & foo() override
{
return x;
}
};
void baz(std::unique_ptr<Foo<int>>)
{
}
int main()
{
auto up = std::make_unique<Bar>();
baz(up);
return 0;
}
It won't compile reporting this error:
prog.cc:27:9: error: could not convert 'up' from 'unique_ptr<Bar,default_delete<Bar>>' to 'unique_ptr<Foo<int>,default_delete<Foo<int>>>'
27 | baz(up);
| ^~
| |
| unique_ptr<Bar,default_delete<Bar>>
I wonder how I can solve this problem. share_ptr
seems to have proper casting methods to solve this issue, while it seems that for unique_ptr
there no alternatives.
Upvotes: 0
Views: 507
Reputation: 13424
First of all, you are taking the argument in baz
by value, which would imply copying a std::unique_ptr
and... that's impossible (or std::move
ing it, but I doubt that's what you want here).
Second of all, std::unique_ptr
doesn't convert because that would require copying.
What's the workaround?
You can do:
std::unique_ptr<Foo<int>> up = std::make_unique<Bar>();
instead of:
auto up = std::make_unique<Bar>();
and take the argument in baz
by reference:
void baz(std::unique_ptr<Foo<int>>&) { ... }
First thing is to save a unique_ptr
to derived in a unique_ptr
to base. auto
cannot do that, unless you use a cast.
Second thing is, as aforementioned, to not copy the unique_ptr
.
What's more, you code exhibits undefined behaviour, because you delete the derived class object with a base class pointer. That requires a virtual
destructor in the base class.
Upvotes: 2