Cla*_*diu 3 c++ lambda templates types c++11
我正在尝试编写一个与Python的过滤器类似的就地过滤器功能.例如:
std::vector<int> x = {1, 2, 3, 4, 5};
filter_ip(x, [](const int& i) { return i >= 3; });
// x is now {3, 4, 5}
Run Code Online (Sandbox Code Playgroud)
首先我尝试了这个:
template <typename Container, typename Filter>
void filter_ip(Container& c, Filter&& f)
{
c.erase(std::remove_if(c.begin(), c.end(), std::not1(f)), c.end());
}
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为lambdas 没有argument_type字段.
以下变体确实有效:
template <typename Container, typename Filter>
void filter_ip(Container& c, Filter&& f)
{
c.erase(std::remove_if(c.begin(), c.end(),
[&f](const typename Container::value_type& x) {
return !f(x);
}),
c.end());
}
Run Code Online (Sandbox Code Playgroud)
然而,似乎不太理想,因为之前,这将只会要求Container有begin,end和erase,而现在它也要求它定义了一个value_type.而且它看起来有点笨拙.
这是这个答案中的第二种方法.第一个将使用std::not1(std::function<bool(const typename Container::value_type&)>(f))而不是lambda,它仍然需要类型.
我还尝试将arg func指定为std::function具有已知参数类型的参数:
template <typename Container, typename Arg>
void filter_ip(Container& c, std::function<bool(const Arg&)>&& f)
{
c.erase(std::remove_if(c.begin(), c.end(), std::not1(f)), c.end());
}
Run Code Online (Sandbox Code Playgroud)
但后来我得到:
'main()::<lambda(const int&)>' is not derived from 'std::function<bool(const Arg&)>'
Run Code Online (Sandbox Code Playgroud)
有没有办法解决?直观地说它似乎应该非常简单,因为你需要做的就是将一个不应用于你已经知道f返回的bool .
如果你不能使用C++ 14泛型lambdas,那么如何委托一个带有模板化的经典仿函数operator():
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
template <class F>
struct negate {
negate(F&& f)
: _f(std::forward<F>(f)) {}
template <class... Args>
bool operator () (Args &&... args) {
return !_f(std::forward<Args>(args)...);
}
private:
F _f;
};
template <typename Container, typename Filter>
void filter_ip(Container& c, Filter&& f)
{
c.erase(std::remove_if(
c.begin(),
c.end(),
negate<Filter>(std::forward<Filter>(f))),
c.end()
);
}
int main() {
std::vector<int> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
filter_ip(v, [](int i) {return bool(i%2);});
for(auto &&i : v)
std::cout << i << ' ';
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
1 3 5 7 9
Run Code Online (Sandbox Code Playgroud)