1.5 std::function和bind绑定器
C++11增加了std::function和std::bind,不仅让我们使用标准库函数时变得更加方便,而且还能方便地实现延迟求值。
1.5.1 可调用对象
在C++中,存在“可调用对象(Callable Objects)”这么一个概念。准确来说,可调用对象有如下几种定义:
1)是一个函数指针。
2)是一个具有operator()成员函数的类对象(仿函数)。
3)是一个可被转换为函数指针的类对象。
4)是一个类成员(函数)指针。
它们在程序中的应用如代码清单1-16所示。
代码清单1-16 可调用对象的使用示例
void func(void) { // ... } struct Foo { void operator()(void) { // ... } }; struct Bar { using fr_t = void(*)(void); static void func(void) { // ... } operator fr_t(void) { return func; } }; struct A { int a_; void mem_func(void) { // ... } }; int main(void) { void(* func_ptr)(void) = &func; // 1. 函数指针 func_ptr(); Foo foo; // 2. 仿函数 foo(); Bar bar; // 3. 可被转换为函数指针的类对象 bar(); void (A::*mem_func_ptr)(void) // 4. 类成员函数指针 = &A::mem_func; int A::*mem_obj_ptr // 或者是类成员指针 = &A::a_; A aa; (aa.*mem_func_ptr)(); aa.*mem_obj_ptr = 123; return 0; }
从上述可以看到,除了类成员指针之外,上面定义涉及的对象均可以像一个函数那样做调用操作。
在C++11中,像上面例子中的这些对象(func_ptr、foo、bar、mem_func_ptr、mem_obj_ptr)都被称做可调用对象。相对应的,这些对象的类型被统称为“可调用类型”。
细心的读者可能会发现,上面对可调用类型的定义里并没有包括函数类型或者函数引用(只有函数指针)。这是因为函数类型并不能直接用来定义对象;而函数引用从某种意义上来说,可以看做一个const的函数指针。
C++中的可调用对象虽然具有比较统一的操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法五花八门。这样在我们试图使用统一的方式保存,或传递一个可调用对象时,会十分烦琐。
现在,C++11通过提供std::function和std::bind统一了可调用对象的各种操作。