До использования 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
Просто используйте 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());
}
Если вы просто хотите удалить некоторое значение из вектора, чем вы можете просто использовать 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