To copy a unique pointer vector to a new vector

When I compile the code below, I get a compilation error:

std::vector<std::unique_ptr<boxIndex>> tmpVec; for(const auto& it: hrzBoxTmpMap){ for(const auto& it2: hrzBoxVec){ std::copy_if(hrzBoxVec.begin(), hrzBoxVec.end(), tmpVec.begin(), [&](std::unique_ptr<boxIndex>& p) { return !(it.second == p->getTop() && it.first != p->getLeft() ); }); } } 

Compilation Error:

 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_algo.h: > In instantiation of '_OIter std::copy_if(_IIter, _IIter, _OIter, > _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<std::unique_ptr<boxIndex>*, std::vector<std::unique_ptr<boxIndex> > >; _OIter = > __gnu_cxx::__normal_iterator<std::unique_ptr<boxIndex>*, std::vector<std::unique_ptr<boxIndex> > >; _Predicate = > smoothHrzIndexing(std::vector<std::unique_ptr<boxIndex> > >&)::<lambda(std::unique_ptr<boxIndex>&)>]': test_word_2.cpp:282:5: required from here > /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_algo.h:990:6: > error: use of deleted function 'std::unique_ptr<_Tp, _Dp>& > std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) > [with _Tp = boxIndex; _Dp = std::default_delete<boxIndex>]' In file > included from > /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/memory:86:0, > from test_word_2.cpp:8: /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/unique_ptr.h:263:19: > error: declared here 

Can someone help me with this?

+7
c ++ vector c ++ 11 const
source share
3 answers

What you can do is use std::move_iterator<...> , using for example something like below (this is SSCCE , demonstrating a crucial point

 #include <iostream> #include <iterator> #include <vector> #include <memory> int main() { std::vector<std::unique_ptr<int>> boxVec; boxVec.emplace_back(new int(1)); boxVec.emplace_back(new int(17)); boxVec.emplace_back(new int(3)); std::vector<std::unique_ptr<int>> tmpVec; std::copy_if(std::make_move_iterator(boxVec.begin()), std::make_move_iterator(boxVec.end()), std::back_inserter(tmpVec), [&](std::unique_ptr<int> const& p){ return *p == 17; }); for (auto const& x: boxVec) { (x? std::cout << *x: std::cout << "<null>") << " "; } std::cout << "\n"; } 

Dereferencing a std::move_iterator<It> will return the appropriate value of an iterator type value. Since the value of r is obtained using std::move(*it) , this is a reference. That is, the value will not be stolen until the value is actually moved. In comparison, const& , i.e. He will not steal value. The assignment will become the rvalue assignment. The code also uses std::back_inserter() to position enough elements at the destination.

I don’t think this is a really solid decision, but I also don’t think that there is such an algorithm as std::move_if() (or setting up any algorithm that leads to the same behavior). To really deal with conditionally moving objects, I think that you have a different access mechanism for the values ​​passed to the predicate, and a way to assign objects (the maps properties will solve these problems, but there is no suggestion yet to add them to the C + standard +).

+6
source share

There is no direct way to do this, but you can link some STL commands to achieve what you want:

  • std::stable_partition or std::partition to split the container in half.
  • std::move to move the values ​​you want to move to a new vector
  • vector.erase to remove old, invalid vector.erase

In the end, you have a clean source vector (all moved, invalid entries deleted) and a clean target vector.

it might look something like this:

 std::vector<std::unique_ptr<int>> source, target; // ... fill data auto it = std::stable_partition(begin(source),end(source),[](std::unique_ptr<int> const& val) { return *val < 3; // your negated condition }); std::move(it,end(source),std::back_inserter(target)); source.erase(it,end(source)); 

Here is a live example

+3
source share

std::unique_ptr movable , not std::unique_ptr .
Thus, you cannot use std::copy_if() with instances of unique_ptr .

If you really want to use std::copy_if() , you can use std::shared_ptr instead of std::unique_ptr , and then if you want to get rid of the old vector content, just destroy it, for example. vector::clear() .

Or, if shared_ptr too much overhead for you, or you need a unique_ptr s vector in any case, then you might want to remove the unnecessary vector elements in place using std::remove_if() and erase-delete the idiom .

0
source share

All Articles