简体   繁体   中英

In-place std::copy_if

It appears to me that std::copy_if would be very useful for filtering containers:

std::vector<int> vec { 1, 2, 3, 4 };
auto itEnd = std::copy_if(vec.begin(), vec.end(), vec.begin(),
                          [](int i) { return i > 2; });
vec.resize(itEnd - vec.begin());

However, std::copy_if is specified that the input and output ranges may not overlap.

Is there an alternative?

copy_if is primarily for copying a range to another range/container Ie by design, the nature of the algorithm is to copy the elements satisfying some condition to another (non-overlapping) range or to a new container.

remove_if is more appropriate for what you need; it is exactly for filtering out as you expect. However, it only removes the elements by overwriting; the remnants between the old and new ends would be unspecified elements after the function's completion and needs to be manually erased using erase , like so:

std::vector<int> vec { 1, 2, 3, 4 };
vec.erase(std::remove_if(std::begin(vec),
                         std::end(vec),
                         [](int i) { return i <= 2; }),
          std::end(vec));

This is a C++ idiom that goes by the name erase-remove .


Instead of copy_if , if copy was what you wanted, then you've an alternative for overlapping ranges, namely copy_backward ; from the documentation

If d_first is within [first, last), std::copy_backward must be used instead of std::copy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM