您可以将任何行为类似于函数的谓词传递给copy_if
。您可以使用一些常见的东西:
1) 功能
函数确实像函数一样工作,因此它们可以作为谓词传递给copy_if
:
bool is_less_than_zero(int i) { return i < 0; }
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
std::copy_if(a.begin(), a.end(), std::back_inserter(b), is_less_than_zero);
// now b will contain the elements {-2, -1}
}
现场演示
2) 具有重载的对象operator()
对象可以重载operator()
以便它们像函数一样起作用。这些通常称为“函数对象”或“函子”。这允许您存储状态,这是使用原始函数无法实现的:
struct IsLessThan {
IsLessThan(int i) : i_{i} {}
bool operator()(int i) { return i < i_; }
int i_;
};
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
std::copy_if(a.begin(), a.end(), std::back_inserter(b), IsLessThan(0));
// now b will contain the elements {-2, -1}
}
现场演示
3) Lambdas
Lambda 在概念上是匿名函数。事实上,它们只是重载对象的语法糖operator()
,但这使它们成为用很少的代码创建简单谓词的有用工具:
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
std::copy_if(a.begin(), a.end(), std::back_inserter(b),
[](int i){ return i < 0; });
// now b will contain the elements {-2, -1}
}
现场演示
由于 lambda 确实是具有重载的对象operator()
它们还可以包含状态,该状态通过 lambda 的捕获列表给出:
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
int number_to_compare_to = 0;
std::copy_if(a.begin(), a.end(), std::back_inserter(b),
[number_to_compare_to](int i){ return i < number_to_compare_to; });
// now b will contain the elements {-2, -1}
}
现场演示
标准库中有一些工具可以轻松创建包含状态的函数对象,并使用它向函数提供一些参数(即std::bind),但在它们有用的大多数地方,现在使用 lambda 更容易。也就是说,以下代码创建两个行为完全相同的对象:
bool first_less_than_second(int i, int j) { return i < j; }
int main() {
auto bind_less_than_zero = std::bind(first_less_than_second, std::placeholders::_1, 0);
auto lambda_less_than_zero = [](int i){ return first_less_than_second(i, 0); };
}
一般来说,您应该更喜欢 lambda 版本,但有时您仍然会看到std::bind
(或其 pre-c++11 boost 对应项boost::bind
) 受雇。