Можете ли вы использовать `std:: remove_if` в контейнере` std:: unique_ptr`?

Учитывая std::vector<std::unique_ptr<SomeType> >, можно ли использовать remove_if на нем? Другими словами, данный код:

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() );

я гарантирую после стирания, что все указатели, все еще находящиеся в v, являются действительный. Я знаю, что, учитывая интуитивную реализацию std::remove_if, и учитывая все реализации, на которые я смотрел, Они будут. Я хотел бы знать, есть ли что-нибудь в стандарте что гарантирует это; то есть, что std::remove_if не разрешено копировать любая из допустимых записей без повторного копирования копии в ее окончательный место нахождения.

(Я, конечно, предполагаю, что условие не копируется. условие имеет подпись типа:

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

то, конечно, все указатели будут недействительными после remove_if.)

Ответ 1

25.3.8 в N3290 говорит о функции удаления:

Требуется: тип * сначала должен удовлетворять MoveAssignable требования (таблица 22).

и

Примечание: каждый элемент в диапазоне [ret, last), где ret - возвращаемый value, имеет действительное, но неопределенное состояние, поскольку алгоритмы могут исключить элементы путем замены или перемещения элементов, которые были первоначально в этом диапазоне.

Это означает, что это зависит от вашего оператора предиката. Поскольку ваш предикат не создает копию, элементы не копируются.

Ответ 2

Точно так же, как erase() и resize(), remove_if() будут перемещать элементы (возможно, с помощью подкачки), поэтому элементы контейнера не нужно копировать. Нет ничего особенного в unique_ptr, это просто другой тип только для перемещения.

Как вы указываете, предикат должен, конечно, принимать элементы по const-ссылке. Опять же, как и для любого подвижного типа.