5

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?

Community
  • 1
  • 1
SimonAx
  • 1,176
  • 1
  • 8
  • 32

2 Answers2

4

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;
};
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • OP may still have the error while trying to `push_back` lvalue of `Foo` as `Foo` is not copy-constructible, this is worth to mention – Piotr Skotnicki Sep 30 '14 at 08:06
  • @PiotrS. The OP claims the error came from the definition of the vector - it did not. And the answer addressed moving the struct itself as well. – Angew is no longer proud of SO Sep 30 '14 at 08:07
  • In VS2013 move constructors can't be defaulted for whatever reason, so you need to define it explicitly (i.e. `: m_Foos(std::move(rhs.m_Foos))`). – riv Feb 02 '16 at 18:46
1

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

Foo(std::unique_ptr<Bar> bar) : m_myBar(std::move(bar)) {}
//                                      ^^^^^^^^^^^^^^
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • @angew and Kerrek. Thanks for pointing out that I cannot type :-s In my original question I forgot to include that I use std::move, which you both mentioned. I've updated my original question to reflect this. When deleting the line std::vector m_Foos, the program compiles and I can even construct Foo objects, so I'm pretty sure that the vector is causing the problem. – SimonAx Sep 30 '14 at 08:07
  • @SimonAx: what operations do you perform over the vector? and do you try to copy that Other class with `std::vector` ? – Piotr Skotnicki Sep 30 '14 at 08:09
  • @PiotrS. I did not perform any operation over the vector yet. Before going further with pushing back elements I wanted to verify that the program compiled and it didn't. – SimonAx Sep 30 '14 at 08:11