分类: C/C++
2013-05-24 17:19:59
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 等二元函数配接.这时候,需要自己写比较函数了.
template<返回值类型,参数类型列表> functor;
象下面:
bool calc(int a,int b)
{
return a < b;
}
使用
Functor
lf(200,300);
还可以将现有的Functor传入构造函数的作为参数
Functor
uff(300,400);
如果用上面的calc函数对STL vector容器进行排序可以这样用
vector
for (i = 0; i < 100; i++) {
lv.push_back(i);
}
//构造一个Functor并传入sort
sort(lv.begin(), lv.end(), Functor
//先定义变量,再传入
Functor
sort(lv.begin(), lv.end(), lf );
//使用stl中的less
std::less
Functor
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(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
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
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
Functor
Functor
Functor
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!
如果函数调用的参数采用值传递的方式,并且参数拷贝构造的开销过大,在写程序的时候
本身就应该注意到这个问题,Loki中也提供了一个很有效的工具TypeTraits,可以用于取
得某种数据类型的特征.
和STL的一样,对于不同调用方式的函数象 __stdcall 调用的函数
bool _stdcall func3(int,int)
{
cout << "func3 be called" << endl;
return 0;
}
Functor
上面的代码dev-cpp编译错误
Loki的Functor利用Typelist的提供功能,扩充了Functor使用的参数的个数,
还提供的参数绑定功能和Chain调用等功能.
其中使用的象策略模板参数,TypeTraits类型特征取得,都是很值得学习的技术.
本篇文章中的代码在dev-cpp4.9 gcc3.3.1环境中编译.