在 C++14 中:
template<class T, class A, class F>
std::vector<T,A> keep_only( std::vector<T,A> input, F&& filter ) {
auto it = std::remove_if( begin(input), end(input), [&](T const& t)->bool {
return !filter(t);
});
input.erase(it, end(input));
return input;
}
auto v2 = keep_only(v1, [](auto&& x){return x.valueX>5;}
在 C++11 中,将 auto&& 替换为 Cell const&。
此版本修改了它所采用的向量的副本。这意味着它复制每个元素,然后丢弃一些元素,并在丢弃过程中移动元素。这在您已经通过副本获取传入向量的情况下更为理想,因为它可以被省略/移动到。如果您的对象复制起来很昂贵并且您丢弃了大部分对象,那么这不是最佳选择。
我们可以通过以下方式使keep_only 不受输入向量的限制:
namespace details {
template<class C, class F>
auto keep_only( C&& input, F&& filter ) {
using std::begin; using std::end;
using T = std::decay_t<decltype(*begin(input))>;
std::vector<T> retval;
std::copy_if(
begin(input), end(input),
std::back_inserter(retval),
std::forward<F>(filter)
);
return retval;
}
}
template<class C, class F>
auto keep_only( C&& input, F&& filter ) {
return details::keep_only(std::forward<C>(input), std::forward<F>(filter));
}
并添加初始化列表支持:
template<class T, class F>
std::vector<T> keep_only( std::initializer_list<T> input, F&& filter ) {
return details::keep_only(input, std::forward<F>(filter));
}
所以你可以输入keep_only( {1,2,3,4,5,6}, [](int x){return x>1;} )
live example
这个版本只复制你告诉它保留的那些。它还会在矢量调整大小期间移动您平均保留一次的元素。无论输入如何,它总是返回一个向量。用 C++11 写这个可能不值得,因为正确推导 T 在函数上下文之外需要一些样板。
您可以通过采用第一个实现并将签名更改为:
template<class T, class A, class F>
std::vector<T,A> keep_only( std::vector<T,A>&& input, F&& filter ) {
并返回return std::move(input);:现在,对于除了临时向量之外的任何内容,我们构造一个向量并将内容复制到其中。对于临时向量,我们改为过滤掉我们不想要的部分。