Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resize a vector of vector of unique_ptr?

How to properly resize a vector of unique_ptr vectors in one line without gcc giving a compilation error regarding a deleted function?

vector<vector<unique_ptr<A> >> a;
a.resize(..... )

UPDATE: This is the code that I used that works OK.

  int width, height;
  vector<vector<unique_ptr<A> >> a;
  a.resize(width);
  for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
          a.at(i).emplace_back(new A());

If possible, I would like to resize the sizes in one go just like resizing of vector of vectors;

vector<vector<int>> intObj;
intObj.resize(width, vector<int>(height, int()));

but I got this error whenever I tried to resize the above vectors using the following method;

a.resize(x, vector<unique_ptr<A>>(y, unique_ptr<A>()));

error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = A; _Dp = std::default_delete<A>]’

Thanks.

like image 684
user2924261 Avatar asked Nov 09 '22 00:11

user2924261


1 Answers

The problem is that vector<unique_ptr<A>> is a non-copyable type, because unique_ptr<A> cannot be copied. a.resize(x, vector<unique_ptr<A>>(y)) uses the copy constructor of the vector<unique_ptr<A>> and a.resize(x, vector<unique_ptr<A>>(y, unique_ptr<A>())) is even worse as it uses the copy constructor of both unique_ptr<A> and vector<unique_ptr<A>>.

Two solutions:

  1. Use a single vector<unique_ptr<A>> that has size x*y. This means a.resize(x*y) will work as intended.
  2. Or, you will need to use a loop over all of the sub vectors.

Example of loop:

a.resize(x);
for (auto& i : a) {
    i.resize(y);
}

EDIT: If you wanted the unique_ptr<A>s to point at default constructed As and not nullptr, then you can use this code:

a.resize(x);
for (auto& i : a) {
    i.reserve(y);
    for (int j = 0; y != j; ++j) {
        i.push_back(std::make_unique<A>());
    }
}

You can't use a single resize call to do what you want if you maintain your current design.

EDIT 2: Here's a one liner for default constructing As if you go with solution 1:

std::generate_n(std::back_inserter(a), x*y, []{ return std::make_unique<A>(); });
like image 172
Simple Avatar answered Nov 14 '22 23:11

Simple