Reputation: 2798
I want to create a list<unique_ptr<Base>> listOfBaseUniquePtr
. This will be able to give me both:
1. Unique ptrs, and
2. Polymorphism. I whould be able to call each derived class virtual function.
Something doesn't work for me. Take a look in the following code example:
#include <iostream>
#include <list>
#include <memory>
using namespace std;
class Base {
};
list<unique_ptr<Base>> listOfBaseUniquePtr;
template <typename T>
class Derived: public Base {
};
int main() {
listOfBaseUniquePtr.push_back(new Derived<int>()); // <--- error
}
Error:
main.cpp:19:53: error: no matching function for call to
‘std::list >::push_back(Derived)’
listOfBaseUniquePtr.push_back(new Derived()); // <--- error
^ main.cpp:19:53: note: candidates are: In file included from /usr/include/c++/4.8/list:63:0,
from main.cpp:2: /usr/include/c++/4.8/bits/stl_list.h:1015:7: note: void std::list<_Tp,
_Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr; _Alloc = std::allocator
std::list<_Tp, _Alloc>::value_type = std::unique_ptr]
push_back(const value_type& __x)
^ /usr/include/c++/4.8/bits/stl_list.h:1015:7: note: no known conversion for argument 1 from ‘Derived’ to ‘const value_type&
{aka const std::unique_ptr&}’
/usr/include/c++/4.8/bits/stl_list.h:1020:7: note: void std::list<_Tp,
_Alloc>::push_back(std::list<_Tp, _Alloc>::value_type&&) [with _Tp = std::unique_ptr; _Alloc = std::allocator
std::list<_Tp, _Alloc>::value_type = std::unique_ptr]
push_back(value_type&& __x)
^ /usr/include/c++/4.8/bits/stl_list.h:1020:7: note: no known conversion for argument 1 from ‘Derived*’ to
‘std::list >::value_type&& {aka
std::unique_ptr&&}’ make[2]:
[CMakeFiles/uniqueptr.dir/main.cpp.o] Error 1 make[1]:
[CMakeFiles/uniqueptr.dir/all] Error 2 make: [all] Error 2
What am I doing wrong?
Upvotes: 3
Views: 4108
Reputation: 2837
If you look at the signature of push_back()
, you will see that there are two overloads. One takes a std::unique_ptr<T> const&
and the other a std::unique_ptr<T>&&
.
The expression new Derived<int>()
returns a Derived<int>*
type; clearly that is not either of the previously mentioned types; none of the overloads have a Derived<int>*
parameter.
You can do two things:
Replace
listOfBaseUniquePtr.push_back(new Derived<int>());
With
listOfBaseUniquePtr.push_back( std::make_unique<Derived<int>>() );
Or, use the emplace()
family of member functions of std::list<T>
; here's an example:
listOfBaseUniquePtr.emplace_back( new Derived<int> );
Your base classes should always have a virtual destructor if classes that derive from that base class are going to be deleted through a pointer of the base class. Your base class' definition should be:
class Base
{
public:
virtual ~Base() = default;
};
Upvotes: 4
Reputation: 50026
You should use std::make_unique:
listOfBaseUniquePtr.push_back(std::make_unique<Derived<int>>());
also dont forget to add virtual destructor to your Base:
virtual ~Base(){}
otherwise ~Derived constructor will not be called if destroyed using base class pointer.
Upvotes: 1