您的位置:首页 > 其它

Boost.Function指南

2009-01-01 22:21 176 查看
原文:http://www.boost.org/doc/libs/1_37_0/doc/html/function/tutorial.html
原作者:boost

版权:本文为Boost的译文,遵守BoostSoftwareLicense-Version1.0协议

Boost.Function指南

基本用法

自由函数

成员函数

函数对象引用

比较Boost.Function和函数对象

Boost.Function有两种语法形式,首选形式和可移槙形式。首选形式更符合C++语言习惯,使用更少量的模板形参,具有更强的可读性。遗憾的是,由于编译器自身的bug,使得并非所有的编译器都支持首选形式。Boost.Function支持的可移槙形式可以在所有编译器上运行。可查阅下表来为你的编译器选择一种适合的形式。

[thead]
[/thead]
首选语法
可移槙语法
GNUC++2.95.x,
3.0.x,3.1.x
ComeauC++4.2.45.2
SGIMIPSpro7.3.0
IntelC++5.0,6.0
Compaq'scxx6.2
MicrosoftVisualC++
7.1

支持首选语法的所有编译器
MicrosoftVisualC++
6.0,7.0
BorlandC++5.5.1
SunWorkShop6
update2C++5.3
Metrowerks
CodeWarrior8.1

如果上表没有你所使用的编译器,请尝试使用首选语法形式,并把使用结果报告给Boost邮件列表,使上表保持最新的信息。

基本用法

简单地说,函数包装器就是function类模板的实例,通过指定返回类型和参数类型,类似于C++函数类型。可以提供任意个数的参数,但不能超过实现时定义的个数限制(默认最大值为10)。下面声明了函数对象包装器f,它要求两个int参数,并返回float结果。

[thead]
[/thead]
首选语法
可移槙语法
boost::function
<float(intx,inty)>f;[/code]
boost::function2
<float,int,int>f;[/code]
默认情况,函数对象包装器是空的,我们可以创建一个函数对象并赋给f。

structint_div{
floatoperator()(intx,inty)const{return((float)x)/y;};
};
f=int_div();


现在我们可以使用f去执行底层的函数对象int_div。

std::cout<<f(5,3)<<std::endl;


任何与f兼容的函数对象都可以分配给f。若int_div声明接受两个long类型的操作数,由f传递给int_div的参数会产生隐式转换,而无须用户介入。这一规则适用于任何可拷贝构造的参数类型,甚至是引用和数组。

[thead]
[/thead]
[thead]
[/thead]
首选语法
boost::function
<void(intvalues[],intn,int&sum,float&avg)>sum_avg;[/code]
可移槙语法
boost::function4
<void,int*,int,int&,float&>sum_avg;[/code]
voiddo_sum_avg(intvalues[],intn,int&sum,float&avg)
{
sum=0;
for(inti=0;i<n;i++)
sum+=values[i];
avg=(float)sum/n;
}
sum_avg=&do_sum_avg;


调用一个没有包含函数对象的函数对象包装器,违背了它的前置条件,如同尝试在空函数指针上调用一样,将会抛出bad_function_call异常。可以在boolean语境中使用函数对象包装器(如果包装器不为空,那么它取值为true),或比较函数对象包装器与0来检查它是否为空函数对象包装器,例如:

if(f)
std::cout<<f(5,3)<<std::endl;
else
std::cout<<"fhasnotarget,soitisunsafetocall"<<std::endl;


另外,empty()函数可以告知该包装器是否为空。

最后,可以清除函数目标,通过用0给它赋值,或调用clear()成员函数,例如:

f=0;


自由函数

自由函数指针可以看成独立的函数对象,拥用const的函数调用操作符;因此它可以直接用在函数对象包装器中:

floatmul_ints(intx,inty){return((float)x)*y;}
f=&mul_ints;


注意符号&不是必须的,除非你正使用MicrosoftVisualC++Version6。

成员函数

很多系统中,回调通常是调用某个特定类的成员函数。这通常涉及“参数绑定”,并超出了Boost.Function的范围。然而Boost.Function支持直接使用成员函数,因此下面代码是合法的:

structX{
intfoo(int);
};


[thead]
[/thead]
首选语法
可移槙语法
boost::function
<int(X*,int)>f;[/code]
f=&X::foo;
Xx;
f(&x,5);
boost::function2
<int,X*,int>f;[/code]
f=&X::foo;
Xx;
f(&x,5);
存在一些库支持参数绑定,下面是三个支持参数绑定库的汇总:

·
Bind。该库允许为任何函数对象进行参数绑定,同时是轻量级的和具有很好的移槙性。

·
C++标准库,一起使用std::bind1st和std::mem_fun把对象绑定到成员函数指针,以供Boost.Function使用:

[thead]
[/thead]
首选语法
可移槙语法
[code]boost::function
<int(int)>f;[/code]
Xx;
f=std::bind1st(
std::mem_fun(&X::foo),&x);
f(5);//Callx.foo(5)
[code]boost::function1
<int,int>f;[/code]
Xx;
f=std::bind1st(
std::mem_fun(&X::foo),&x);
f(5);//Callx.foo(5)
·
Lambda库,它使用非常地道的C++语法,提供一种强大的组合机制来构造函数对象。Lambda要求编译器要相当好地尊盾C++标准。

函数对象引用

在某些情况下,让Boost.Function去拷贝一个函数对象是昂贵的(或语义错误的)。在此情况下,很可能要求Boost.Function只保存函数对象的引用。可通过使用ref和cref函数把引用包装成一个函数对象来实现。

[thead]
[/thead]
首选语法
可移槙语法
stateful_typea_function_object;
boost::function
<int(int)>f;[/code]
f=[code]boost::ref
(a_function_object);[/code]
boost::function
<int(int)>f2(f);[/code]
stateful_typea_function_object;
boost::function1
<int,int>f;[/code]
f=[code]boost::ref
(a_function_object);[/code]
boost::function1
<int,int>f2(f);[/code]
这里f没有拷贝a_function_object对象,f2也一样,只是关注f中指向a_function_object的引用。另外,使用函数对象的引用给Boost.Function赋值,或传给它的构造函数,将不会抛出异常。

比较Boost.Function和函数对象

函数对象包装器可以通过==或!=与能储存在该包装器内的任何函数对象作比较。若函数对象包装器内包含的是函数对象,则把内在的函数对象与给定的函数对象作比较(它们必须是EqualityComparable或已重载
boost::function_equal
)。例如:

intcompute_with_X(X*,int);
f=&X::foo;
assert(f==&X::foo);
assert(&compute_with_X!=f);


函数对象包装器与
reference_wrapper
的实例比较时,则把
reference_wrapper
中对象的地址和函数对象包装器内储存对象的地址作比较。


a_stateful_objectso1,so2;
f=[code]boost::ref
(so1);[/code]
assert(f==[code]boost::ref
(so1));[/code]
assert(f==so1);//Onlyifa_stateful_objectisEqualityComparable
assert(f!=[code]boost::ref
(so2));[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: