10

I try to move some unique_ptr in a vector during it declaration and I get a error. I think that I make a copy without knowing it.

I don't understand why I get the problem at the declaration while it works very well during a push_back.

I simplified the problem in few lines.

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

int main() {

    unique_ptr<int> i1 = make_unique<int>(142);
    unique_ptr<int> i2 = make_unique<int>(242);
    unique_ptr<int> i3 = make_unique<int>(342);


    vector<unique_ptr<int>> v;

    //Those lines work
    v.push_back(move(i1));
    v.push_back(move(i2));
    v.push_back(move(i3));

    //ERROR
    vector<unique_ptr<int>> v2 {move(i1), move(i2), move(i3)}; 

    return 0;
}

The error is :

use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const
std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp =
std::default_delete<int>]'
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

What am I missing ?

Thanks !

3Dave
  • 28,657
  • 18
  • 88
  • 151
Nix
  • 351
  • 5
  • 13
  • worth noting, depending on the problem you are trying to solve, you could just do a `v.emplace_back(make_unique(142));` – RyanP Jan 12 '17 at 15:13
  • 1
    also worth noting, in your example `i1`, `i2` and `i3` are empty (already moved from) when creating `v2`. – simon Jan 12 '17 at 15:15
  • 1
    See http://stackoverflow.com/questions/9618268/initializing-container-of-unique-ptrs-from-initializer-list-fails-with-gcc-4-7 – Christian Hackl Jan 12 '17 at 15:17

2 Answers2

7

When you do

vector<unique_ptr<int>> v2 {move(i1), move(i2), move(i3)};

you are not actually moving directly into the vector v2. Instead the compiler will create a std::initializer_list of the moved unique pointers, and pass that list object to the std::vector constructor which will then attempt to copy the elements from the initializer list.

Unfortunately I know of no way to solve the problem, of using the intermediate initializer list to initialize a vector of unique pointers.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

The line

vector<unique_ptr<int>> v2 {move(i1), move(i2), move(i3)}; 

creates a std::initializer_list, which only provides access to its members via reference-to-const. This initializer_list is constructed by moving from each unique_ptr, but the vector is then initialised by copying elements from the initializer_list. It's this copy that causes your compilation error.

Andrew
  • 5,212
  • 1
  • 22
  • 40