5
votes

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?

2
Are you using Visual Studio?Angew is no longer proud of SO
No, I'm using Qt Creator 3.1.2 based on Qt 5.3.1 with mingw32-make.exe. Does that matter?SimonAx
Which compiler? I assume mingw gcc, which should be OK. Visual Studio's compiler cannot generate move ctors automatically. But the vector line itself is not causing the error, see link in my answer. Is it perhaps enclosed in a class, which would affect that class's copy ctor? IOW, please post an MCVE.Angew is no longer proud of SO

2 Answers

4
votes

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

You cannot copy unique pointers. You can only move them:

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