I'm using std::remove_if to move a selection of std::vector elements to the end so that I can copy them to another vector then erase the range:
using ElemPtr = std::shared_ptr<Elem>;
auto iter = std::remove_if(source.begin(),source.end(), [&](const ElemPtr& e){ /* ... */ });
dest.insert(dest.end(),iter,source.end());
source.erase(iter,source.end());
What happens is that after the call to std::remove_if, the values to be removed have their destructor called (ie. they are set to null). I end up just copying a bunch of null pointers, which isn't great.
Resources like cppreference.com do not have any mention of this behaviour so I am wondering if this is a compiler bug?
I am using gcc 5.2.0.
std::remove_if does not move elements to be removed to the end. Instead, it moves elements not to be removed to the front; the contents of the tail are left unspecified.
In the process, some elements that the predicate says should be removed may be overwritten by (to be precise, assigned from) other elements. For an element that's a shared_ptr, this means it may very well destroy the underlying object.
What you seem to be looking for is std::partition. It behaves exactly the way you seem to expect std::remove_if to behave.
It's not a bug. In fact, they're not destructor called, they're just moved. Their dtor won't be called until container's erase get called.
cppreference.com mentioned that,
Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range. Relative order of the elements that remain is preserved and the physical size of the container is unchanged. Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). A call to remove is typically followed by a call to a container's erase method, which erases the unspecified values and reduces the physical size of the container to match its new logical size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With