boost::bind的简单实现

  在上一篇blog中简单的实现了boost::function,支持带有2个参数的函数/函数指针,函数对象,函数适配器/bind类,以及带有1个参数的成员函数指针。

  本文接着来介绍如何实现一个简单的boost::bind。

  基本目标如下:

  1、支持接收0个参数的函数/函数指针,函数对象。

  2、支持接收1个参数的函数/函数指针,函数对象。

  3、支持接收2个参数的函数/函数指针,函数对象。

  首先,解决占位符的问题:

 1 namespace
 2 {
 3
 4 struct Placeholders1
 5 {
 6 } _1;
 7
 8 struct Placeholders2
 9 {
10 } _2;
11
12 }

使用匿名namespace的原因是防止不同编译单元中的命名冲突, 让占位符对象只在其所在的编译单元中可见。

  在boost::bind源码中主要是通过2个list表维持各种相关信息。一个bindlist表维持了bind接收的绑定参数,包括占位符,用户传入的变量等。一个calllist维持了调用bind返回的对象时所传入的参数信息。它们的通过继承层次的方式来表现的。

  下面这个继承层次的每一个类都要作为对应的bindlist和calllist层次中的基类,它们分别保存了bind接收的绑定参数信息(用户传入的变量,占位符),以及调用bind返回的对象时所传入的参数信息。

 1 class Base0
 2 {
 3 };
 4
 5 template<typename T1>
 6 class Base1 : public Base0
 7 {
 8 public:
 9     Base1(T1 data1)
10         : data1_(data1)
11     {
12     }
13
14 protected:
15     T1 data1_;
16 };
17
18 template<typename T1, typename T2>
19 class Base2 : public Base1<T1>
20 {
21 public:
22     Base2(T1 data1, T2 data2)
23         : Base1<T1>(data1), data2_(data2)
24     {
25     }
26
27 protected:
28     T2 data2_;
29 };

  接着,就是所谓的calllist的实现了。它们的基类将保存调用bind返回的对象时所传入的参数信息。

 1 class CallList0 : public Base0
 2 {
 3 public:
 4     template<typename _T>
 5     _T operator[](_T arg)
 6     {
 7         return arg;
 8     }
 9 };
10
11 template<typename T1>
12 class CallList1 : public Base1<T1>
13 {
14 public:
15     CallList1(T1 data1)
16         : Base1<T1>(data1)
17     {
18     }
19
20     T1 operator[](Placeholders1 arg1)
21     {
22         return Base1<T1>::data1_;
23     }
24
25     template<typename _T>
26     _T operator[](_T arg)
27     {
28         return arg;
29     }
30
31 };
32
33 template<typename T1, typename T2>
34 class CallList2: public Base2<T1, T2>
35 {
36 public:
37     CallList2(T1 data1, T2 data2)
38         : Base2<T1, T2>(data1, data2)
39     {
40     }
41
42     T1 operator[](Placeholders1 arg1)
43     {
44         return Base2<T1, T2>::data1_;
45     }
46
47     T2 operator[](Placeholders2 arg2)
48     {
49         return Base2<T1, T2>::data2_;
50     }
51
52     template<typename _T>
53     _T operator[](_T arg)
54     {
55         return arg;
56     }
57 };

  然后,我们来看看bindlist,它们的基类主要保存了bind接收的占位符、参数信息。

 1 class CallList0 : public Base0
 2 {
 3 public:
 4     template<typename _T>
 5     _T operator[](_T arg)
 6     {
 7         return arg;
 8     }
 9 };
10
11 template<typename T1>
12 class CallList1 : public Base1<T1>
13 {
14 public:
15     CallList1(T1 data1)
16         : Base1<T1>(data1)
17     {
18     }
19
20     T1 operator[](Placeholders1 arg1)
21     {
22         return Base1<T1>::data1_;
23     }
24
25     template<typename _T>
26     _T operator[](_T arg)
27     {
28         return arg;
29     }
30 };
31
32 template<typename T1, typename T2>
33 class CallList2: public Base2<T1, T2>
34 {
35 public:
36     CallList2(T1 data1, T2 data2)
37         : Base2<T1, T2>(data1, data2)
38     {
39     }
40
41     T1 operator[](Placeholders1 arg1)
42     {
43         return Base2<T1, T2>::data1_;
44     }
45
46     T2 operator[](Placeholders2 arg2)
47     {
48         return Base2<T1, T2>::data2_;
49     }
50
51     template<typename _T>
52     _T operator[](_T arg)
53     {
54         return arg;
55     }
56 };

  接下来就是bind函数所返回的对象了,相信童鞋们可以想象的到,这个对象中应该主要保存的是bind函数接收的参数信息咯,并且他还保存了所注册的函数。

 1 template<typename Func, typename Bind>
 2 class BindImpl
 3 {
 4 public:
 5     BindImpl(Func func, Bind bindlist)
 6         : func_(func), bindlist_(bindlist)
 7     {
 8     }
 9
10     void operator()()
11     {
12         bindlist_(func_);
13     }
14
15     template<typename T1>
16     void operator()(T1 data1)
17     {
18         bindlist_(func_, CallList1<T1>(data1));
19     }
20
21     template<typename T1, typename T2>
22     void operator()(T1 data1, T2 data2)
23     {
24         bindlist_(func_, CallList2<T1, T2>(data1, data2));
25     }
26
27 protected:
28     Func func_;
29     Bind bindlist_;
30 };

  如此,基本的轮廓就已经出来了。bind函数返回一个BindImpl对象,里面保存了注册的函数和bind接收的占位符、参数信息。当我们调用这个对象的时候,会生成一个calllist对象,它保存了调用BindImpl对象时所传入的参数,然后在bindlist中调用注册的函数。

  需要的注意的是,在bindlist调用函数时我们转而调用了calllist的operator[]函数,通过它来判断传入的参数是占位符还是用户传入的参数,如果是占位符,那么就返回calllist中保存的之前注册的用户传入的信息。如果不是占位符,operator[]函数就单纯的返回他接收的参数,也就是之前用户调用BindImpl时传入的参数。

  最后,我们通过一组重载的bind函数来实现对接收0个参数、1个参数、2个参数的支持,它们返回的是一个BindImpl对象。

 1 template<typename Func, typename Bind>
 2 class BindImpl
 3 {
 4 public:
 5     BindImpl(Func func, Bind bindlist)
 6         : func_(func), bindlist_(bindlist)
 7     {
 8     }
 9
10     void operator()()
11     {
12         bindlist_(func_);
13     }
14
15     template<typename T1>
16     void operator()(T1 data1)
17     {
18         bindlist_(func_, CallList1<T1>(data1));
19     }
20
21     template<typename T1, typename T2>
22     void operator()(T1 data1, T2 data2)
23     {
24         bindlist_(func_, CallList2<T1, T2>(data1, data2));
25     }
26
27 protected:
28     Func func_;
29     Bind bindlist_;
30 };
31
32 template<typename Func>
33 BindImpl<Func, BindLinst0> bind(Func func)
34 {
35     return BindImpl<Func, BindLinst0>(func, BindLinst0());
36 }
37
38 template<typename Func, typename T1>
39 BindImpl<Func, BindList1<T1> > bind(Func func, T1 data1)
40 {
41     return BindImpl<Func, BindList1<T1> >(func, BindList1<T1>(data1));
42 }
43
44 template<typename Func, typename T1, typename T2>
45 BindImpl<Func, BindList2<T1, T2> > bind(Func func, T1 data1, T2 data2)
46 {
47     return BindImpl<Func, BindList2<T1, T2> >(func, BindList2<T1, T2>(data1, data2));
48 }

  这样bind函数的基本功能就实现了,但是需要提到的是,目前的bind并不支持注册成员函数。如果要支持成员函数注册的话,需要萃取函数指针的返回类型,每个参数类型,具体方法在上一篇blog《boost::function的简单实现》中介绍到了,有兴趣的童鞋可以去看看。

  下面就来简单的测试一下:

 1 int get(int a, int b)
 2 {
 3     std::cout << a + b << std::endl;
 4     return 0;
 5 }
 6
 7 class Point
 8 {
 9 public:
10     int operator()(int a, int b)
11     {
12         std::cout << "Point::operator() called: a = " << a + b << std::endl;
13         return a + b;
14     }
15 };
16
17 int main(int argc, char const *argv[])
18 {
19     bind(get, _1, 10)(20, 1);
20     bind(Point(), _1, _2)(3, 4);
21     return 0;
22 }

  结果为:

30
Point::operator() called: a = 7

  得到的结果正如预期的一样。

(完)

时间: 2024-10-01 03:05:42

boost::bind的简单实现的相关文章

Boost::Bind 基础

先了解一下:函数对象 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.[1] 一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)"的方式使用一个 类对象,如果没有上下文,完全可以把它看作一个函数对待.这是通过重载类的 operator()来实现的.比如,对于调用 int s = sum(1, 1); 你可能把它看作一个函数调用: int sum(int i, int j) { return i+j; } 但很可能

boost::bind 介绍

boost::bind 介绍 这篇文章介绍boost::bind()的用法, 文章的主要内容是参考boost的文档. 1. 目的 boost::bind 是std::bindlist 和 std::bind2nd的结合体.它提供一个任意的函数对象(仿函数).函数.函数指针.成员函数指针. 它可以绑定任意的参数.bind 没有对函数对象有任何的要求. 2. 把bind()用在函数和函数指针上 有如下代码: 1 void f(int a, int b) 2 { 3 cout << a + b &l

(转)boost::bind介绍

转自:http://www.cnblogs.com/sld666666/archive/2010/12/14/1905980.html 这篇文章介绍boost::bind()的用法, 文章的主要内容是参考boost的文档. 1. 目的 boost::bind 是std::bindlist 和 std::bind2nd的结合体.它提供一个任意的函数对象(仿函数).函数.函数指针.成员函数指针. 它可以绑定任意的参数.bind 没有对函数对象有任何的要求. 2. 把bind()用在函数和函数指针上

Boost::bind使用详解

1.Boost::bind 在STL中,我们经常需要使用bind1st,bind2st函数绑定器和fun_ptr,mem_fun等函数适配器,这些函数绑定器和函数适配器使用起来比较麻烦,需要根据是全局函数还是类的成员函数,是一个参数还是多个参数等做出不同的选择,而且有些情况使用STL提供的不能满足要求,所以如果可以我们最好使用boost提供的bind,它提供了统一的接口,提供了更多的支持,比如说它增加了shared_ptr,虚函数,类成员的绑定. 2.bind的工作原理 bind并不是一个单独的

Boost::bind学习

1什么是函数对象 2Boostbind 绑定自由函数 绑定全部参数 不绑定全部参数 绑定类的函数 boostbind绑定的值是拷贝形式的值传递 1.什么是函数对象 在了解函数对象之前,应该先知道什么是函数指针,函数指针不再介绍了.函数对象用起来比函数指针更加灵活,且可以实现内联函数. 函数对象是具有函数功能的对象.怎么才能使对象具有函数的功能呢?答案是重载操作符().加入要实现两个整数相加: class Add { public: int operator()( int a, int b) {

bind的简单配置

bind的简单配置 摘要:DNS  bind简单配置        FQDN        http://www.178linux.com.  WWW是主机名  .178linux.COM.是私有域名  .com.是DNS一级域名 .是根域 DNS解析顺序 /etc/hosts→DNS缓存→DNS域服务器 主机优先查找本地的hosts(/etc/hosts)文件,没有想对应的记录则去查找本地DNS客户端的解析缓存库,缓存库没有想对应的记录则询问本地配置的DNS服务器(DNS服务器配饰文件 /et

boost::bind 详解

使用 boost::bind是标准库函数std::bind1st和std::bind2nd的一种泛化形式.其可以支持函数对象.函数.函数指针.成员函数指针,并且绑定任意参数到某个指定值上或者将输入参数传入任意位置. 1. 通过functions和function pointers使用bind 给定如下函数: 1 int f(int a, int b) 2 { 3 return a + b; 4 } 5 6 int g(int a, int b, int c) 7 { 8 return a + b

0801-----C++Primer听课笔记----------C++11新特性 function 和 bind 的简单使用

1.function 和 函数指针 1.1 function有函数指针的功能,但是使用起来明显比函数指针更加灵活和方便. 1.2 函数指针和function的用法实例. 1.2.1 函数指针首先要清楚函数指针的类型,如void (*)(int, char)等,然后声明一函数指针变量直接调用即可. #include <iostream> using namespace std; /* * 函数指针的用法 */ void test(int i,double j){ cout << i

boost::bind boost::function

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <boost/bind.hpp> #include <boost/function.hpp> #include <iostream&g