Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error while declaring a class with std::vector of structs containing std::unique_ptr

Although having worked several years with C#, getting things done in C++ is sometime still difficult for me. I fully embrace the usage of smart pointers, but now I'm facing the following puzzle

I have a struct Foo, e.g.

struct Foo
{
    Foo(std::unique_ptr<Bar> bar) : m_myBar(std::move(bar)) {}

 private:
    std::unique_ptr<Bar> m_myBar;           
};

In a different class, I want to have a vector containing instances of Foo, but the following line

 std::vector<Foo> m_Foos;

yields compile errors saying that the copy constructor is deleted. In the SO thread "Why can I not push_back a unique_ptr into a vector?" an explanation as well as a remedy is given. However, there the question concerns a vector of unique pointers whereas I have a vector of structs containing a unique pointer. The suggested solution is to use move semantics, but how does that apply in my situation? Or should I be doing something else?

like image 875
SimonAx Avatar asked Sep 30 '14 07:09

SimonAx


People also ask

What is std :: Unique_ptr?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

What is make_ unique in c++?

You can use make_unique to create a unique_ptr to an array, but you cannot use make_unique to initialize the array elements. C++ Copy. // Create a unique_ptr to an array of 5 integers. auto p = make_unique<int[]>(5); // Initialize the array. for (int i = 0; i < 5; ++i) { p[i] = i; wcout << p[i] << endl; }

How does std:: make_ unique work?

std::make_uniqueConstructs an object of type T and wraps it in a std::unique_ptr. 1) Constructs a non-array type T . The arguments args are passed to the constructor of T . The function does not participate in the overload resolution if T is an array type.


1 Answers

As you say, m_Foos is actually a data member of another class (I'll call it FooHolder). If you didn't provide a copy constructor for FooHolder, the compiler will generate one automatically. That copy constructor will call the copy constructors of all data members of FooHolder, including m_Foos. Of course, the copy constructor of std::vector<Foo> contains a compilation error, since Foo is not copyable. This is probably why you're getting the error.

You'll have to provide an appropriate copy constructor for FooHolder, if you are able to and want that class to be copyable. Otherwise, you can just declare a move constructor (possibly defaulted), which will make the copy constructor deleted:

struct FooHolder
{
  FooHolder(FooHolder&&) = default;

private:
  std::vector<Foo> m_Foos;
};
like image 122
Angew is no longer proud of SO Avatar answered Sep 22 '22 15:09

Angew is no longer proud of SO