std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。
下面看一个示例,如代码清单1-17所示。
代码清单1-17 std::function的基本用法
#include <iostream> // std::cout #include <functional> // std::function void func(void) { std::cout << __FUNCTION__ << std::endl; } class Foo { public: static int foo_func(int a) { std::cout << __FUNCTION__ << "(" << a << ") ->: "; return a; } }; class Bar { public: int operator()(int a) { std::cout << __FUNCTION__ << "(" << a << ") ->: "; return a; } }; int main(void) { std::function<void(void)> fr1 = func; // 绑定一个普通函数 fr1(); // 绑定一个类的静态成员函数 std::function<int(int)> fr2 = Foo::foo_func; std::cout << fr2(123) << std::endl; Bar bar; fr2 = bar; // 绑定一个仿函数 std::cout << fr2(123) << std::endl; return 0; } 运行结果如下: func foo_func(123) ->: 123 operator()(123) ->: 123
从上面我们可以看到std::function的使用方法,当我们给std::function填入合适的函数签名(即一个函数类型,只需要包括返回值和参数表)之后,它就变成了一个可以容纳所有这一类调用方式的“函数包装器”。
再来看如代码清单1-18所示的例子。
代码清单1-18 std::function作为回调函数的示例
#include <iostream> // std::cout #include <functional> // std::function class A { std::function<void()> callback_; public: A(const std::function<void()>& f) : callback_(f) {} void notify(void) { callback_(); // 回调到上层 } }; class Foo { public: void operator()(void) { std::cout << __FUNCTION__ << std::endl; } }; int main(void) { Foo foo; A aa(foo); aa.notify(); return 0; }
从上面的例子中可以看到,std::function可以取代函数指针的作用。因为它可以保存函数延迟执行,所以比较适合作为回调函数,也可以把它看做类似于C#中特殊的委托(只有一个成员的委托)。
同样,std::function还可以作为函数入参,如代码清单1-19所示。
代码清单1-19 std::function作为函数入参的示例
#include <iostream> // std::cout #include <functional> // std::function void call_when_even(int x, const std::function<void(int)>& f) { if (!(x & 1)) // x % 2 == 0 { f(x); } } void output(int x) { std::cout << x << " "; } int main(void) { for(int i = 0; i < 10; ++i) { call_when_even(i, output); } std::cout << std::endl; return 0; } 输出结果如下: 0 2 4 6 8
从上面的例子中可以看到,std::function比普通函数指针更灵活和便利。
在下一节我们可以看到当std::function和std::bind配合起来使用时,所有的可调用对象(包括类成员函数指针和类成员指针)都将具有统一的调用方式。