其实在研究bind前我也一直很疑惑,我们可以延迟调用函数,却不知道如何传递当时的环境情况,绑定可以,虽然loki只提供了BindFirst,但是递归是loki还有你我都已经达成的共识。
BindFirst接受Functor,而且返回Functor,你可以想像,它一定内部对传入的Functor进行了某种转换、拷贝仰或赋值。我们来看BindFirst函数:
template
<
class
Fctor
>
BindFirst(
const
Fctor
&
fun,typename Fctor::Param1 bound)
...
{ typedef Fctor::BoundFunctorType Outgoing; return Outgoing(std::auto_ptr < typename Outgoing::Impl > ( new BinderFirst < Fctor > (fun,bound))); }
BindFirst只是一个助手函数,它负责创建一个新的FunctorImpl,而此处的FunctorImpl 接受一个额外的参数:Fctor::Parm1,可以想象,新的Impl一定是内部保存了这个参数,在调用的时候进行的参数传递。
和开发其他FunctorImpl一样,BinderFirst可以被轻易完成,只是你一看记住需要记录一个额外的参数。
template
<
class
Incoming
>
class
BinderFirst :
public
FunctorImpl
<
typename Incoming::ResultType,typename Incoming::Arguments::Tail
>
...
{ typedef Functor < typename Incoming::ResultType,Incoming::Arguments::Tail > Outgoing; typedef typename Incoming::Parm1 Bound; typedef typename Incoming::ResultType ResultType; public : BinderFirst( const Incoming & fun,Bound bound) :fun_(fun),bound_(bound) ... {} // ... ResultType operator ()() ... { return fun_(bound_); } ResultType operator ()(typename Outgoing::Parm1 p1) ... { return fun_(bound_,p1); } ResultType operator ()(typename Outgoing::Parm1 p1,typename Outgoing::Parm2 p2) ... { return fun_(bound_,p1,p2); } private : Incoming fun_; Bound bound_; }
;
MCD里对对这段代码解释的不好,而且它的代码可能是直接拷贝loki里的东西,名称空间还在,要详细了解这部分,建议看loki代码这部分。
如你所见,BindFirst是方法,你可以在任何阶段使用它,这有别于类似typelist的编译期推到的思想,这也就是说,运行阶段的任意合法操作(编译期未知行为)都可以使用BindFirst。
int
doadd(
int
a,
int
b)
...
{ return a + b; }
int
_tmain(
int
argc, _TCHAR
*
argv[])
...
{ Functor < int ,LOKI_TYPELIST_2( int , int ) > cmd1(doadd); Functor < int ,LOKI_TYPELIST_1( int ) > cmd2(BindFirst(cmd1, 1 )); Functor < int > cmd3(BindFirst(cmd2, 1 )); cout << cmd3() << endl; Functor < int > cmd4(BindFirst(cmd2,cmd3())); cout << " cmd4() = " << cmd4() << endl; for ( int i = 0 ;i < 10 ; ++ i) ... { Functor < int > cmd5(BindFirst(cmd2,i * i)); cout << i << " : " << cmd5() << endl; } return 0 ; }