Рассмотрим следующий сценарий:
bool is_odd(int i)
{
return (i % 2) != 0;
}
int main()
{
// ignore the method of vector initialization below.
// assume C++11 is not to be used.
std::vector<int> v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> v2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// removes all odd numbers, OK
v1.erase( std::remove_if(v1.begin(), v1.end(), is_odd), v1.end() );
// remove all even numbers
v2.erase( std::remove_if(v2.begin(), v2.end(), ???), v2.end() );
}
Могу ли я использовать то же самое is_odd()
UnaryPredicate для удаления четных чисел, как и ожидалось в последней строке main()
, Или я должен обязательно написать is_even()
хотя это будет только
bool is_even(int i)
{
!is_odd(i);
}
проверить станд :: not1 функция. он делает то, что вы хотите.
v2.erase( std::remove_if(v2.begin(), v2.end(), std::not1(std::ptr_fun(is_odd))), v2.end() );
В любом случае, если это зависит от меня, плюс C ++ 11 доступен, я бы предпочел:
v2.erase( std::remove_if(v2.begin(), v2.end(), [&](auto/* or the type */ const& item){return !is_odd(item);}), v2.end() );
потому что, насколько я помню std::not1
было полезно раньше lambda
был доступен.
Ты можешь использовать std::not1
, К сожалению, std::not1
требует аргумента объекта функции с вложенным argument_type
а также result_type
типы. То есть его нельзя использовать напрямую. Вместо этого необходимо сочетать использование с std::ptr_fun
при использовании отрицателя с нормальной функцией:
v2.erase( std::remove_if(v2.begin(), v2.end(), std::not1(std::ptr_fun(is_odd))), v2.end() );
На последнем заседании комитета std::not_fn
был перенесен из Основы библиотеки TS 2 в рабочий проект. То есть есть надежда, что с C ++ 17 есть лучшее предложение для общего отрицателя.
В общем, веселье прекращается, когда вам нужно использовать любой из std::*_fun
функции. Как уже отмечали другие, разумно использовать вместо этого лямбду:
v2.erase( std::remove_if(v2.begin(), v2.end(), [](auto&& x){ return !::is_odd(x); }), v2.end() );
Использование лямбда-функции или функционального объекта с inline
Оператор вызова функции также имеет преимущество в том, что компилятору легче вставлять код.
Очевидно, что если вам нужно использовать C ++ до C ++ 11, std::not1
/std::ptr_fun
подход является самым простым для немедленного использования, а использование лямбда-функции даже невозможно. В этом случае вы можете создать простой объект функции для поддержки встраивания:
struct not_odd {
template <typename T>
bool operator()(T const& value) const { return !::odd(value); }
};
// ...
v2.erase( std::remove_if(v2.begin(), v2.end(), not_odd()), v2.end() );