1
votes

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?

2
push_back(make_unique<Derived<int>>()) should do the job.Jarod42

2 Answers

4
votes

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;
};
1
votes

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.