Boost::bind源码分析:bind.hpp

2014-11-24 12:10:56 · 作者: · 浏览: 0

bind实质上是一个函数。
#ifndef BOOST_BIND
#define BOOST_BIND bind
#endif
在此文件内将其定义为BOOST_BIND.以下均以BOOST_BIND代指bind.

template
_bi::bind_t
BOOST_BIND(F f)
{
typedef _bi::list0 list_type;
return _bi::bind_t (f, list_type());
}

此函数的返回值是_bi::bind_t,参数是F,这是针对无参函数的版本。
_bi是文件中定义于boost命名空间之下的一个命名空间,bind实现的细节均在其中(bind implementation).
下面看bind_t定义:

template class bind_t
{
public:

typedef bind_t this_type;

bind_t(F f, L const & l): f_(f), l_(l) {}

#define BOOST_BIND_RETURN return
#include
#undef BOOST_BIND_RETURN
};

看起来很小,只有一个类型定义和一个构造函数。但注意include那一句,这意味着整个bind_template.hpp文件都
是bind_t类的一部分。而bind_tmplate文件差不多有350行。因为函数体都很小,所以直接在类内定义,成为inline.所以,当要定义的一个类特别大时,将其具体的函数
实现放置于另一个文件中也是一个很好的办法。
下面来看bind_template.hpp中属于_bi::bind_t的一些成员定义。
typedef typename result_traits::type result_type; result_traits
提取返回值。在bind.hpp中将其定义为R。
result_type operator()()
{
list0 a;
BOOST_BIND_RETURN l_(type(), f_, a, 0);
}
后面依次是operator()的const版本,一直到九个参数的版本。BOOST_BIND_RETURN可以直接当作return.
list0类也有九个。


看一个例子
int f()
{
return 1;
}
bind(f)()应该等于f().
bind函数中返回值是: _bi::bind_t (f, list_type());list_type=_bi::list0。所以返回值是一个特化的模板类。
f的类型为int (*)(),即是F。所以返回值是 www.2cto.com
_bi::bind_t(f,_bi::list0());
R为萃取出的返回值(int)。通过此构造函数,构造出了一个bind_t类,f,list0,分别由bind_t的相应私有数据存储起来。
然后是调用此类(函数体).即bind(f)(),bind_t重载了相应的()运算符。
还是依参数个数不同有不同的表现形式,此例没有参数,其表现形式为:
result_type operator()()
{
list0 a;
BOOST_BIND_RETURN l_(type(), f_, a, 0);
}
返回值即为原来的int.函数实现这一块交给list0(l_).list0(type(),f,a,0).
type()生成了一个空的类。l_已经是一个生成的类,所以此处调用的是重载操作符().
template R operator()(type, F & f, A &, long)
{
return unwrapper::unwrap(f, 0)();
}

又调用unwrapper结构体。因为是static,所以不用再生成类的实例,最后返回的就是原来的那个f()------->int。
template struct unwrapper
{
static inline F & unwrap( F & f, long )
{
return f;
}

template static inline F2 & unwrap( reference_wrapper rf, int )
{
return rf.get();
}

template static inline _mfi::dm unwrap( R T::* pm, int )
{
return _mfi::dm( pm );
}
};

其他参数不同的情况与此类似。bind对不同数目的参数都有相应一致的处理方式。但是依据相应类的个数以及bind的重载个数,参数值最多只能有9个。这样限制一般也
没什么大的影响,因为一般的参数个数没有这么多。如果用的参数有太多的话,其实可以在源码上再加上一种重载形式即可。

上面的实现绕了这么大的一圈,其实最后调用的还是原来的那个函数,看似费时,其实都是为了泛型的必要。bind能够绑定的函数类型大大地增加,不管是普通的函数
指针,还是函数体,以及没有result_type的类型,bind都可以很好的运作。而且还可以与ref库结合起来使用。

C++的这些第三方库里面,BOOST是比较特别的一个。因为它并不是专注于一个问题,而是涉及到了语言的各个层面。有很多接近于语言底层的特性,所以BOOST库比
任何一个库都更值得我们去研究,揣摩。

摘自 逍遥之魂