I have strange issue with std::list of unique_ptr's.
Class slFlyingMonster is derived from class slMonster.
Following code works:
std::unique_ptr<slMonster> ptr(new slFlyingMonster(md));
But this code:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(new slFlyingMonster(md));
throws error:
"Error 1 error C2664: 'void
std::list>,std::allocator>>>::push_back(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : cannot convert argument 1 from 'slFlyingMonster *' to 'std::unique_ptr> &&'"
While I understand, that something is wrong, like std::list.push_back() is not the same as =, but I cannot figure out how to correctly add new class as unique_ptr to list. Any suggestions would be very welcome.
Use push_back
when you have an object of the type which your list contains, and you want to push its copy. Normally, if you don't have such an object yet (in your case, you don't), you're better off initialising a new object directly in the list — using emplace_back
instead:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));
However, as @SebastianRedl correctly pointed out in the comments, the above has a problem of not being exception-safe. If the internal allocation of a new node inside std::list
throws, the new slFlyingMonster
instance would be leaked. emplace_back
is not the correct choice when one of the arguments is an unprotected resource (such as a raw pointer owning memory).
So you actually want to construct a wrapper smart pointer and push it into the list. In C++14, you can do this with std::make_unique
:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(std::make_unique<slFlyingMonster>(md));
With plain C++11, you can either implement your own make_unique
, or explicitly create the smart pointer:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(std::unique_ptr<slMonster>(new slFlyingMonster(md)));
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