如何模拟remove_unless

eri*_*rip 6 c++ erase-remove-idiom c++11 c++14

我有代码删除std::vector<int>少于一些的所有元素int limit.我写了一些部分应用lambdas的函数:

auto less_than_limit = [](int limit) {
  return [=](int elem) {
    return limit > elem;
  };
};

auto less_than_three = less_than_limit(3);
Run Code Online (Sandbox Code Playgroud)

当我测试它时std::vector<int> v{1,2,3,4,5};,我得到了预期的结果:

for(auto e: v) {
  std::cout << less_than_three(e) << " ";
}
// 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

我可以轻松删除少于三个的所有元素:

auto remove_less_than_three = std::remove_if(std::begin(v), std::end(v), less_than_three);

v.erase(remove_less_than_three, v.end());

for(auto e: v) {
  std::cout << e << " ";
}
// 3 4 5
Run Code Online (Sandbox Code Playgroud)

如何使用less_than_three?删除大于或等于3的元素?

我试过包装less_than_threestd::not1,却得到了错误:

/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/stl_function.h:742:11: error: no type named 'argument_type' in 'struct main()::<lambda(int)>::<lambda(int)>'
     class unary_negate
           ^
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/stl_function.h:755:7: error: no type named 'argument_type' in 'struct main()::<lambda(int)>::<lambda(int)>'
       operator()(const typename _Predicate::argument_type& __x) const

/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/predefined_ops.h:234:30: error: no match for call to '(std::unary_negate<main()::<lambda(int)>::<lambda(int)> >) (int&)'
  { return bool(_M_pred(*__it)); }
                              ^
Run Code Online (Sandbox Code Playgroud)

然后我尝试了std::not1(std::ref(less_than_three)),但是遇到了这些错误:

/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/stl_function.h:742:11: error: no type named 'argument_type' in 'class std::reference_wrapper<main()::<lambda(int)>::<lambda(int)> >'
     class unary_negate
           ^
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/stl_function.h:755:7: error: no type named 'argument_type' in 'class std::reference_wrapper<main()::<lambda(int)>::<lambda(int)> >'
       operator()(const typename _Predicate::argument_type& __x) const
       ^
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/predefined_ops.h:234:30: error: no match for call to '(std::unary_negate<std::reference_wrapper<main()::<lambda(int)>::<lambda(int)> > >) (int&)'
  { return bool(_M_pred(*__it)); }
                              ^
Run Code Online (Sandbox Code Playgroud)

如何在std::remove_if不改变lambdas逻辑的情况下否定函数?换句话说,我该如何模仿remove_unless

Col*_*mbo 11

not1 有点过时(并要求函子提供某些成员typedef,lambda显然不会这样).

你必须自己写一个否定词:

auto negate = [] (auto&& f) {return [f=std::forward<decltype(f)>(f)] 
            (auto&&... args) {return !f(std::forward<decltype(args)>(args)...);};};
Run Code Online (Sandbox Code Playgroud)

演示.


Jer*_*fin 7

std::not1假设您的函数对象将派生自std::unary_function或至少提供相同的接口,因此它将具有result_type和的typedef argument_type.

由于lambda不会定义那些,你将无法使用not1它们.

显而易见的选择是创建类似于您not1自己的东西,但使用更现代的技术来检测/传递参数/结果类型.

如果你真的想使用not1,那么最明智的方法是与你进行比较std::lessstd::bind指定你要比较的值(即,它基本上是一个C++ 03的东西,所以如果你要去要使用它,你可以用C++ 03)的方式编写所有内容.