## Function
### 头文件: `"boost/function.hpp"`
头文件 `"function.hpp"` 包含了带有从0到10个参数的函数原型(这是实现所定义的,在当前实现中缺省的上限就是10\[1\])。你也可以根据你的需要,只包含相应参数数量的头文件,文件名为 `"function/functionN.hpp"`, 其中N可以从0到10。Boost.Function有两种不同的接口,其中一种的好处在于它的语法接近于函数声明(而且不要求函数的签名包含参数的数量),另一种接口的好处在于可以在多个编译器中工作。选择哪一种接口,至少部分地取决于你使用的编译器。如果可以,就使用我们称为首选语法(preferred syntax)的那种。在本章中,两种格式都会用到。
> \[1\] Boost.Function 可以配置为支持多达127个参数。
### 使用首选语法的声明
一个 `function` 的声明包括该 `function` 所兼容的函数或函数对象的签名以及返回类型。结果以及参数的类型以单个参数的方式全部提供给模板。例如,声明一个 `function` ,它返回 `bool` 并接受一个类型 `int` 的参数,如下:
```
boost::function<bool (int)> f;
```
可以在括号中给出参数列表,以逗号分隔,就象普通的函数声明一样。所以,声明一个没有返回值(`void`)并带有类型分别为 `int` 和 `double` 的两个参数的函数,就象这样:
```
boost::function<void (int,double)> f;
```
### 使用兼容语法的声明
声明 `function`s 的第二种方法是,分别给出函数调用的返回类型及参数类型作为模板类型参数。并且,要在 `function` 类的名字中加上后缀,后缀是一个表示 `function` 可接受的参数数量的整数。例如,声明一个返回 `bool` 并接受一个类型 `int` 的参数的函数,方法如下:
```
boost::function1<bool,int> f;
```
这里的数字是对应函数可接受的参数数量,在上例中有一个参数(`int`),所以是 `function1` 。更多的参数就意味着要给出更多的模板类型参数并且改变这个数字后缀。一个 `function` ,返回 `void` 并接受类型为 `int` 和 `double` 的两个参数,如下:
```
boost::function2<void,int,double> f;
```
事实上,这个库由一组类组成,其中每个类带有不同数量的参数。如果包含头文件 `"function.hpp"` 就无需关心这一点,但如果包含带数字的头文件,你就必须包含正确数字的头文件。
首选语法更容易阅读,也更象在声明一个函数,所以你应该尽可能使用它。不幸的是,虽然首选语法是完全 合法的C++并且更易读,但是还不是所有编译器都可以支持它。如果你的编译器正好不能处理这种语法,你就必须使用另一种格式。如果你需要编写最大兼容性的 代码,你也只能选择使用另一种格式。让我们来看一下 `function` 的接口中最重要的部分。
### 成员函数
```
function();
```
缺省构造函数创建一个空的函数对象。如果一个空的 `function` 被调用,将会抛出一个类型为 `bad_function_call` 的异常。
```
template <typename F> function(F g);
```
这个泛型的构造函数接受一个兼容的函数对象,即这样一个函数或函数对象,它的返回类型与被构造的 `function` 的返回类型或者一样,或者可以隐式转换,并且它的参数也要与被构造的 `function` 的参数类型或者一样,或者可以隐式转换。注意,也可以使用另外一个 `function` 实例来进行构造。如果这样做,并且 `function f` 为空,则被构造的 function 也为空。使用空的函数指针和空的成员函数指针也会产生空的 `function` 。
```
template <typename F> function(reference_wrapper<F> g);
```
这个构造函数与前一个类似,但它接受的函数对象包装在一个 `reference_wrapper` 中,这用以避免通过值来传递而产生函数或函数对象的一份拷贝。这同样要求函数对象兼容于 `function` 的签名。
```
function& operator=(const function& g);
```
赋值操作符保存 `g` 中的函数或函数对象的一份拷贝;如果 `g` 为空,被赋值的函数也将为空。
```
template<typename F> function& operator=(F g);
```
这个泛型赋值操作符接受一个兼容的函数指针或函数对象。注意,也可以用另一个 `function` 实例(带有不同但兼容的签名)来赋值。这同样意味着,如果 `g` 是另一个 `function` 实例且为空,则赋值后的函数也为空。赋值一个空的函数指针或空的成员函数指针也会使 `function` 为空。
```
bool empty() const;
```
这个成员函数返回一个布尔值,表示该 function 是含有一个函数/函数对象或是为空。如果有一个目标函数或函数对象可被调用,它返回 `false` 。因为一个 function 可以在一个布尔上下文中测试,或者与0进行比较,因此这个成员函数可能会在未来版本的库中被取消,你应该避免使用它。
```
void clear();
```
这个成员函数清除 `function`, 即它不再关联到一个函数或函数对象。如果 function 已经是空的,这个调用没有影响。在调用后,function 肯定为空。令一个 function 为空的首选方法是赋0给它;`clear` 可能在未来版本的库中被取消。
```
operator safe_bool() const
```
这个转型函数返回一个未指定类型(由 `safe_bool` 表示),它可以用于布尔上下文中。如果 `function` 为空,返回值为 `false`. 如果 function 中保存了一个函数指针或函数对象,则返回值为 `true`. 注意,使用一个不同于 `bool` 的类型,可以使得这个转型函数十分安全且不会被重载干扰,同时还提供了直接在布尔上下文中测试 `function` 实例的惯用法。它等同于表达式 `!!f`, 其中 `f` 为一个 `function` 实例。
```
result_type operator()(Arg1 a1, Arg2 a2, ..., ArgN aN) const;
```
调用操作符是调用 `function` 的方法。你不能调用一个空的 `function` ,那样会抛出一个 `bad_function_call` 异常,即当 `!f.empty()`, `if (f)`, 或 `if (!!f)` 返回 `true` 时。调用操作符的执行会调用 `function` 中的函数或函数对象,并返回它的结果。
- 序
- 前言
- Acknowledgments
- 关于作者
- 本书的组织结构
- Boost的介绍
- 字符串及文本处理
- 数 据结构, 容器, 迭代器, 和算法
- 函数对象及高级编程
- 泛 型编程与模板元编程
- 数学及数字处理
- 输入/输出
- 杂项
- Part I: 通用库
- Library 1. Smart_ptr
- Smart_ptr库如何改进你的程序?
- 何时我们需要智能指针?
- Smart_ptr如何适应标准库?
- scoped_ptr
- scoped_array
- shared_ptr
- shared_array
- intrusive_ptr
- weak_ptr
- Smart_ptr总结
- Library 2. Conversion
- Conversion 库如何改进你的程序?
- polymorphic_cast
- polymorphic_downcast
- numeric_cast
- lexical_cast
- Conversion 总结
- Library 3. Utility
- Utility 库如何改进你的程序?
- BOOST_STATIC_ASSERT
- checked_delete
- noncopyable
- addressof
- enable_if
- Utility 总结
- Library 4. Operators
- Operators库如何改进你的程序?
- Operators
- 用法
- Operators 总结
- Library 5. Regex
- Regex库如何改进你的程序?
- Regex 如何适用于标准库?
- Regex
- 用法
- Regex 总结
- Part II: 容器及数据结构
- Library 6. Any
- Any 库如何改进你的程序?
- Any 如何适用于标准库?
- Any
- 用法
- Any 总结
- Library 7. Variant
- Variant 库如何改进你的程序?
- Variant 如何适用于标准库?
- Variant
- 用法
- Variant 总结
- Library 8. Tuple
- Tuple 库如何改进你的程序?
- Tuple 库如何适用于标准库?
- Tuple
- 用法
- Tuple 总结
- Part III: 函数对象与高级编程
- Library 9. Bind
- Bind 库如何改进你的程序?
- Bind 如何适用于标准库?
- Bind
- 用法
- Bind 总结
- Library 10. Lambda
- Lambda 库如何改进你的程序?
- Lambda 如何适用于标准库?
- Lambda
- 用法
- Lambda 总结
- Library 11. Function
- Function 库如何改进你的程序?
- Function 如何适用于标准库?
- Function
- 用 法
- Function 总结
- Library 12. Signals
- Signals 库如何改进你的程序?
- Signals 如何适用于标准库?
- Signals
- 用法
- Signals 总结