Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you use `std::remove_if` on a container of `std::unique_ptr`?

Tags:

c++

c++11

Given an std::vector<std::unique_ptr<SomeType> >, is it legal to use remove_if on it? In other words, given this code:

std::vector<std::unique_ptr<SomeType> > v;
//  fill v, all entries point to a valid instance of SomeType...
v.erase( std::remove_if( v.begin(), v.end(), someCondition ), v.end() );

, am I guaranteed after the erase that all pointers still in v are valid. I know that given the intuitive implementation of std::remove_if, and given all of the implementations I've looked at, they will be. I'd like to know if there is anything in the standard which guarantees it; i.e. that std::remove_if is not allowed to copy any of the valid entries without recopying the copy into its final location.

(I am, of course, supposing that the condition doesn't copy. If the condition has a signature like:

struct Condition
{
    bool operator()( std::unique_ptr<SomeType> ptr ) const;
};

, then of course, all of the pointers will be invalid after remove_if.)

like image 763
James Kanze Avatar asked Dec 07 '11 12:12

James Kanze


People also ask

How does std:: remove work?

std::remove : It doesn't actually delete elements from the container but only shunts non-deleted elements forwards on top of deleted elements. vector::erase : Removes from the vector either a single element (position) or a range of elements ([first, last)).

What STD remove returns?

std :: remove Transforms the range [first,last) into a range with all the elements that compare equal to val removed, and returns an iterator to the new end of that range. The function cannot alter the properties of the object containing the range of elements (i.e., it cannot alter the size of an array or a container).

How does remove if work C++?

C++ Algorithm remove_if() function is used to eliminate all the elements that satisfy a predicate from a given range [first, last) without disturbing the order of the remaining elements. This function cannot alter the size of the container. It returns an iterator to the new end of the range.


2 Answers

Just like erase() and resize(), remove_if() will move elements (possibly via swapping), so the container elements do not need to be copyable. There's nothing special about unique_ptr, it's just another move-only type.

As you point out, the predicate should of course take elements by const-reference. Again, just like for any movable type.

like image 128
Kerrek SB Avatar answered Oct 07 '22 14:10

Kerrek SB


25.3.8 in the N3290 speaks about remove function :

Requires: The type of *first shall satisfy the MoveAssignable requirements (Table 22).

and

Note: each element in the range [ret,last), where ret is the returned value, has a valid but unspecified state, because the algorithms can eliminate elements by swapping with or moving from elements that were originally in that range.

This means that it depends on your predicate operator. Since your predicate doesn't create a copy, then the elements are not going to be copied.

like image 24
BЈовић Avatar answered Oct 07 '22 15:10

BЈовић