Function库实现了一个泛型的回调机制。它提供了函数指针、函数对象和成员函数指针的存储和后续的调用。当然,它与binder库,如 Boost.Bind 和 Boost.Lambda一起工作,大大提高了回调(包括带态度的回调函数)的使用机会。Function常用于需要把函数指针用于回调的地方。例如:信号/接收者的实现,GUI与业务逻辑的分离,以及在标准库容器中存储不同的类函数类型。Function已被即将发布的Library Technical Report所接受。
Function 库如何改进你的程序?
保存函数指针和函数对象,用于后续的调用
在含有回调的设计中,常常需要保存函数和函数对象,而且某些函数或类也是通过函数指针或函数对象来配制其客户化功能。传统上,通常使用函数指针来实现回调及延迟调用的函数。但是,仅仅使用函数指针会有很多限制,更好的方法是采用泛型机制来定义要被保存的函数的署名特征,而让调用者来决定提供哪一种类型的函数实体(函数指针或函数对象)。这样就可以使用任何行为类似于函数的实体,例如,使用 Boost.Bind 和 Boost.Lambda 所返回的结果。这意味着可以给这些被保存的函数增加状态(因为函数对象是一种类)。这种泛化由 Boost.Function 提供。这个库用于保存并然后调用函数或函数对象。
Function 如何适用于标准库?
本库提供了当前标准库所不具备的功能。在那些对商业逻辑的表示层进行解耦的框架中,使用泛型回调是非常自然的、常见的。由于C++标准库不支持保存函数指针和函数对象以供稍后的调用,因此这个工具为标准库提供了非常重要的扩展。而且,本库完全兼容于标准库的绑定器(bind1st 和 bind2nd),就象前面所讨论过的其它绑定器一样,如 Boost.Bind 和 Boost.Lambda.
Function
头文件: "boost/function.hpp"
头文件 "function.hpp" 包含了带有从0到10个参数的函数原型(这是实现所定义的,在当前实现中缺省的上限就是10)。你也可以根据你的需要,只包含相应参数数量的头文件,文件名为 "function/functionN.hpp", 其中N可以从0到10。Boost.Function有两种不同的接口,其中一种的好处在于它的语法接近于函数声明(而且不要求函数的签名包含参数的数量),另一种接口的好处在于可以在多个编译器中工作。选择哪一种接口,至少部分地取决于你使用的编译器。如果可以,就使用我们称为首选语法(preferred syntax)的那种。在本章中,两种格式都会用到。
使用首选语法的声明
一个 function 的声明包括该 function 所兼容的函数或函数对象的签名以及返回类型。结果以及参数的类型以单个参数的方式全部提供给模板。例如,声明一个 function ,它返回 bool 并接受一个类型 int 的参数,如下:
- boost::function<bool (int)> f;
- boost::function<void (int,double)> f;
声明 functions 的第二种方法是,分别给出函数调用的返回类型及参数类型作为模板类型参数。并且,要在 function 类的名字中加上后缀,后缀是一个表示 function 可接受的参数数量的整数。例如,声明一个返回 bool 并接受一个类型 int 的参数的函数,方法如下:
- boost::function1<bool,int> f;
- boost::function2<void,int,double> f;
首选语法更容易阅读,也更象在声明一个函数,所以你应该尽可能使用它。不幸的是,虽然首选语法是完全合法的C++并且更易读,但是还不是所有编译器都可以支持它。如果你的编译器正好不能处理这种语法,你就必须使用另一种格式。如果你需要编写最大兼容性的代码,你也只能选择使用另一种格式。让我们来看一下 function 的接口中最重要的部分。
成员函数
- function();
- template <typename F> function(F g);
- template <typename F> function(reference_wrapper<F> g);
- function& operator=(const function& g);
- template<typename F> function& operator=(F g);
- bool empty() const;
- void clear();
- operator safe_bool() const
- result_type operator()(Arg1 a1, Arg2 a2, ..., ArgN aN) const;
用法
要开始使用 Boost.Function, 就要包含头文件 "boost/function.hpp", 或者某个带数字的版本,从 "boost/function/function0.hpp" 到 "boost/function/function10.hpp". 如果你知道你想保存在 function 中的函数的参数数量,这样做可以让编译器仅包含需要的头文件。如果包含 "boost/function.hpp", 那么就会把其它的头文件也包含进去。
理解被存函数的最佳方法是把它想象为一个普通的函数对象,该函数对象用于封装另一个函数(或函数对象)。这个被存的函数的最大用途是它可以被多次调用,而无须在创建 function 时立即使用。在声明 functions 时,声明中最重要的部分是函数的签名。这部分即是告诉 function 它将保存的函数或函数对象的签名和返回类型。我们已经看到,有两种方法来执行这个声明。这里有一个完整的程序,程序声明了一个 boost::function ,它可以保存返回 bool (或某个可以隐式转换为 bool 的类型)并接受两个参数的类函数实体,第一个参数可以转换为 int, 第二个参数可以转换为 double.
#include <iostream>
#include "boost/function.hpp"
bool some_func(int i,double d) {
return