Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1319672
  • 博文数量: 244
  • 博客积分: 1039
  • 博客等级: 少尉
  • 技术积分: 1562
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-06 09:40
文章分类

全部博文(244)

文章存档

2021年(2)

2019年(6)

2018年(2)

2014年(1)

2013年(187)

2012年(47)

分类: C/C++

2013-05-24 17:19:59

http://blog.csdn.net/hdqqq/article/details/593877

Loki Functor

Loki库中使用Typelist提供的功能,使得该库中Functor可接受的参数个数有了很大的扩充,
其在VC6版本的库中,Functor的参数最多个数为15个.

Loki库中提供的Functor用于一般的函数指针和成员函数或者Functor,所以Loki中并没有提供类似STL
中的一些比较Functor,象

//一元
negate

//二元
plus
minus
multiplies
divides
modulus
equal_to
not_equal_to
greater
greater_equal
less
less_equal
logical_and
logical_or
logical_not

这些,所以,如果你想用Loki中的Functor配接STL的标准算法,象排序等,就会视你使用的编译器版本而定了,如vc6的编译器对模板支持不是很好,Loki中的Functor根本没法和stl中的 less 等二元函数配接.这时候,需要自己写比较函数了.


Loki Functor的一般用法

template<返回值类型,参数类型列表> functor;

象下面:

bool calc(int a,int b)
{
  return a < b;
}

使用

Functor lf(calc);
lf(200,300);

还可以将现有的Functor传入构造函数的作为参数

Functor uff(lf);
uff(300,400);

如果用上面的calc函数对STL vector容器进行排序可以这样用


vector lv;
for (i = 0; i < 100; i++) {
lv.push_back(i);
}

//构造一个Functor并传入sort
sort(lv.begin(), lv.end(), Functor(calc) );

//先定义变量,再传入
Functor lf(calc);
sort(lv.begin(), lv.end(), lf );

//使用stl中的less

std::less stl_less;
Functor lf(stl_less);
sort(lv.begin(), lv.end(), lf );  //这种用法vc6不支持, devcpp gcc 支持, vs2003没有测试.


参数绑定

参数绑定可以在Functor被调用之前先指定一个参数,对于STL中的find_if和count_if
都需要预先指定某个可以进行比较的值.

Loki库中提供了绑定功能的函数

BindFirst(Functor, 第一个参数)

于STL中的bind2nd不同的是,它只绑定Functor的第一个参数,但是可以循环调用,因此可以
支持不同参数个数的Functor的参数绑定.

象下面的代码:

int be_bind_func(int a,int b)
{
 cout << "the first param is " << a << endl;
 cout << "the second param is " << b << endl;
 return a+b;
}

Functor lf(be_bind_func);
lf(100,200);
BindFirst(lf,211)(322);
BindFirst(BindFirst(lf, 300) , 400)();

而STL的bind1st和bind2nd只支持二元函数.

 

链式调用

Loki还提供了一个函数Chain,提供可以对作为参数传入的Functor进行调用


如:

bool be_bind_func(int a,int b)
{
 cout << "the first param is " << a << endl;
 cout << "the second param is " << b << endl;
 return 0;
}

bool calc(int a,int b)
{
 cout << "calc be called " << a << " " << b << endl;
 return a < b;
}

bool func3(int,int)
{
 cout << "func3 be called" << endl;
 return 0;
}


 //进行链式调用
void chain_call()
{
 Functor f1(be_bind_func),f2(calc), f3(func3);
 Chain(f1,Chain(f2,f3))(100,200);
}


//输出结果
the first param is 100
the second param is 200
calc be called 100 200
func3 be called

成员函数Functor


Loki成员函数Functor和一般的Functor的使用方式相同,只需要在Functor的构造函数中传入需要绑定的
类对象和类对象中的成员函数就可以了.
如下面的代码

struct mem_func_struct
{
 void mem_func1() {
  cout << "mem_func_struct::mem_func1() called!" << endl;
 }
 void mem_func2(int) {
  cout << "mem_func_struct::mem_func2(int) called!" << endl;
 }
 void mem_func3(int,int) {
  cout << "mem_func_struct::mem_func3(int,int) called!" << endl;
 }   
 void mem_func4(int,int,int) {
  cout << "mem_func_struct::mem_func4(int,int,int) called!" << endl;
 }
};   

void mem_functor_test()
{
 mem_func_struct lm;
 Functor f1(&lm,&mem_func_struct::mem_func1);
 Functor f2(&lm,&mem_func_struct::mem_func2);
 Functor f3(&lm,&mem_func_struct::mem_func3);
 Functor f4(&lm,&mem_func_struct::mem_func4);
 f1();
 f2(100);
 f3(111,222);
 f4(1,2,3);
}   
//输出的结果

mem_func_struct::mem_func1() called!
mem_func_struct::mem_func2(int) called!
mem_func_struct::mem_func3(int,int) called!
mem_func_struct::mem_func4(int,int,int) called!


其他方面

Functor调用中传递参数的代价

如果函数调用的参数采用值传递的方式,并且参数拷贝构造的开销过大,在写程序的时候
本身就应该注意到这个问题,Loki中也提供了一个很有效的工具TypeTraits,可以用于取
得某种数据类型的特征.

调用方式

和STL的一样,对于不同调用方式的函数象 __stdcall 调用的函数

bool _stdcall func3(int,int)
{
 cout << "func3 be called" << endl;
 return 0;
}

Functor f3(func3);
上面的代码dev-cpp编译错误


小结:

Loki的Functor利用Typelist的提供功能,扩充了Functor使用的参数的个数,
还提供的参数绑定功能和Chain调用等功能.
其中使用的象策略模板参数,TypeTraits类型特征取得,都是很值得学习的技术.


本篇文章中的代码在dev-cpp4.9 gcc3.3.1环境中编译.

阅读(1450) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~