Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

To copy a vector of unique pointer into new vector

When I compile the below code, 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() );
        });
    }
}

The compilation error is:

/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 on this?

like image 703
user3665224 Avatar asked Jul 21 '14 14:07

user3665224


1 Answers

What you could do is to use std::move_iterator<...> using, e.g., something like below (this is a SSCCE demonstrating the 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 a suitable rvalue of the iterator's value type. Since the rvalue is obtained using std::move(*it), it is a reference. That is, the value isn't stolen until the value is actually moved. The comparison uses a const&, i.e., it won't steal the value. The assignment will become an rvalue assignment. The code also uses std::back_inserter() to arrange for enough elements to be in the destination.

I don't think this is really a solid solution but I also don't think there is an algorithm like std::move_if() (or a customization of any algorithm resulting in the same behavior). To really deal with conditionally moving objects I think you'd different access mechanism for the values passed into the predicate and the the way objects are assigned (property maps would address these issues but there is no proposal, yet, to add them to the C++ standard).

like image 105
Dietmar Kühl Avatar answered Nov 09 '22 06:11

Dietmar Kühl