возникли проблемы с vector.erase () и remove_if ()

До использования remove_if я использовал remove. Скажем, если бы я имел vec = {1, 2, 2, 2, 5} и хотел удалить все 2, я бы сделал:

for (vector<int>::iterator it = vec.begin(); it!= vector.end(); ++it){
if (*it == 2){
vec.erase(remove(vec.begin(),vec.end(), *it), vec.end());
}
}

Это не будет работать, так как невозможно и нелогично перебирать вектор по мере удаления.

Итак, я обнаружил remove_if (). Однако по какой-то причине я не могу заставить его работать в контексте класса. Вот мой код:

class SomeClass{
private:
vector<int> vec;
public:
SomeClass(){
//initalizae vec to {1,2,2,2,4,5,6,8}
}
bool is_even(int value){
return value % 2 == 0;
}
void delete(int a){
vec.erase(remove_if(vec.begin(), vec.end(), a), vec.end());
}
void delete_even(int a){
vec.erase(remove_if(vec.begin(), vec.end(), this->is_even(a)), vec.end());
}

Я предполагаю, что void delete не будет работать, потому что a является int, и мне нужно значение bool, но я не уверен, как выразить «если int a находится в этом векторе, вернуть true» в качестве третьего параметра для remove_if. И я ожидаю, что void delete_even будет работать, но я получаю

note: in instantiation of function template specialization 'std::__1::remove_if<std::__1::__wrap_iter<int *>, bool>' requested here

0

Решение

Просто используйте std::remove удалить int Значение из коллекции, не ища ее самостоятельно:

vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());

Это удалит все случаи 2 от vec,

Использование remove_if то же самое, только тогда, а не элемент, который вы задаете предикат (обычно функция); если вам доступен C ++ 11, вы можете использовать его с лямбдой как таковой:

vec.erase(std::remove_if(vec.begin(), vec.end(), [](int a) {return a % 2 == 0;}), vec.end());

Если вы хотите использовать is_even в качестве предиката remove_if (или другая функция-член вашего класса), тогда, как уже упоминалось в комментариях, вы должны сделать ее статической функцией-членом, предпочтительно.
Вы также можете bind для нестатичных участников, но здесь нет реальной причины делать это; но посмотри Используя std :: bind с функцией-членом, использовать указатель объекта или нет для этого аргумента? если вам интересно, сам вопрос содержит правильный синтаксис.
Образец для is_even как статический:

 static bool is_even(int value) {
return value % 2 == 0;
}

void delete_even(int a){
vec.erase(remove_if(vec.begin(), vec.end(), is_even), vec.end());
}
1

Другие решения

Если вы просто хотите удалить некоторое значение из вектора, чем вы можете просто использовать remove()

foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());

Если вы хотите удалить все четные числа, то вместо использования функции-члена класса я бы предложил использовать лямбду.

foo.erase(std::remove_if(foo.begin(), foo.end(), [](auto n) { return n % 2 == 0;}), foo.end());

Вот пример, использующий оба подхода

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
std::vector<int> foo = {1,2,3,4,5,6,7,8,9};
// remove all even numbers
foo.erase(std::remove_if(foo.begin(), foo.end(), [](auto n) { return n % 2 == 0;}), foo.end());
for (auto e : foo)
std::cout << e << std::endl;
std::cout << std::endl;
// remove all elemenets that match some_value
foo = {1,2,2,2,2,2,7,8,9};
int some_value = 2;
foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());
for (auto e : foo)
std::cout << e << std::endl;
}

Выход:

1
3
5
7
9

1
7
8
9

Живой пример

1

По вопросам рекламы [email protected]