频道栏目
首页 > 程序开发 > 软件开发 > C++ > 正文
Boost::bind源码分析:bind.hpp
2012-04-05 09:57:53      个评论      
收藏   我要投稿

bind实质上是一个函数。
#ifndef BOOST_BIND
#define BOOST_BIND bind
#endif
在此文件内将其定义为BOOST_BIND.以下均以BOOST_BIND代指bind.
 
template<class R, class F>
    _bi::bind_t<R, F, _bi::list0>
    BOOST_BIND(F f)
{
 typedef _bi::list0 list_type;
 return _bi::bind_t<R, F, list_type> (f, list_type());
}
 
此函数的返回值是_bi::bind_t<R,F,_bi::list0>,参数是F,这是针对无参函数的版本。
_bi是文件中定义于boost命名空间之下的一个命名空间,bind实现的细节均在其中(bind implementation).
下面看bind_t定义:
 
template<class R, class F, class L> 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 <boost/bind/bind_template.hpp>
#undef BOOST_BIND_RETURN
};
 
看起来很小,只有一个类型定义和一个构造函数。但注意include那一句,这意味着整个bind_template.hpp文件都
是bind_t类的一部分。而bind_tmplate文件差不多有350行。因为函数体都很小,所以直接在类内定义,成为inline.所以,当要定义的一个类特别大时,将其具体的函数
实现放置于另一个文件中也是一个很好的办法。
下面来看bind_template.hpp中属于_bi::bind_t的一些成员定义。
typedef typename result_traits<R, F>::type result_type; result_traits
提取返回值。在bind.hpp中将其定义为R。
    result_type operator()()
    {
        list0 a;
        BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
    }
后面依次是operator()的const版本,一直到九个参数的版本。BOOST_BIND_RETURN可以直接当作return.
list0类也有九个。


看一个例子
int f()
{
    return 1;
}
bind(f)()应该等于f().
bind函数中返回值是: _bi::bind_t<R, F, list_type> (f, list_type());list_type=_bi::list0。所以返回值是一个特化的模板类。
f的类型为int (*)(),即是F。所以返回值是 www.2cto.com
_bi::bind_t<int, int(*)(),_bi::list0>(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<result_type>(), f_, a, 0);
    }
返回值即为原来的int.函数实现这一块交给list0(l_).list0(type<int>(),f,a,0).
type<int>()生成了一个空的类。l_已经是一个生成的类,所以此处调用的是重载操作符().
    template<class R, class F, class A> R operator()(type<R>, F & f, A &, long)
    {
        return unwrapper<F>::unwrap(f, 0)();
    }

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

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

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

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

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

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

 

摘自  逍遥之魂
 
点击复制链接 与好友分享!回本站首页
相关TAG标签 源码
上一篇:游戏中的资源管理部分的设计(C++语言描述)
下一篇:CString TrimRight 的问题
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站