c++11 boost - bind、function

2018-07-13 17:17:23

bind 是对 c++98 函数适配器 bind1st/bind2nd 的泛化和增强,可以适配任意的可调用对象,包括函数指针、函数引用、成员函数指针、函数对象和 lambda 表达式。

bind 最多可以绑定9个函数参数。

// Copyright (c) 2015
// Author: Chrono Law
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
//using namespace std;

#include <boost/bind.hpp>
using namespace boost;

//////////////////////////////////////////

int f(int a, int b)
{   return a + b;}

int g(int a, int b, int c)
{   return a + b * c;}

//typedef int (*f_type)(int, int);
//typedef int (*g_type)(int, int, int);
typedef decltype(&f) f_type;
typedef decltype(&g) g_type;

void case1()
{
	//绑定参数并调用
    std::cout << bind(f,1,2)() << std::endl;
    std::cout << bind(g,1,2,3)() << std::endl;

    //f_type fp = f;
    //std::cout << bind(fp, _1, _2)(1,2) << std::endl;

    int x = 1, y = 2, z = 3;

    bind(f, _1,  9)(x) ;   //f(x, 9)
    bind(f, _1, _2)(x, y) ; //f(x,y)
    bind(f, _2, _1)(x, y) ; //f(y,x)
    bind(f, _1, _1)(x, y) ; //f(x,x)
    bind(g, _1, 8, _2)(x, y) ; //g(x,8,y)
    bind(g, _3, _2, _2)(x, y, z) ; //g(z,y,y)

    f_type pf = f;
    g_type pg = g;

    std::cout << bind(pf, _1, 9)(x) << std::endl; //(*pf)(x,9)
    std::cout << bind(pg, _3, _2, _2)(x, y, z) << std::endl;  //(*pg)(z,y,y)

}

struct demo
{
    int f(int a, int b)
    {   return a + b;   }
};

struct point
{
    int x, y;
    point(int a = 0, int b = 0):x(a),y(b){}
    void print()
    {   std::cout << "(" << x << "," << y << ")\n";  }
};

//绑定成员函数
void case2()
{
    demo a,&ra=a;
    demo *p = &a;

    std::cout << bind(&demo::f, a, _1, 20)(10) << std::endl;
    std::cout << bind(&demo::f, ra, _2, _1)(10, 20) << std::endl;
    std::cout << bind(&demo::f, p, _1, _2)(10, 20) << std::endl;

    std::vector<point> v(10);
    std::for_each(v.begin(), v.end(), bind(&point::print, _1));
}

void case3()
{
    std::vector<point> v(10);
    std::vector<int> v2(10);

    std::transform(v.begin(), v.end(), v2.begin(), bind(&point::x, _1));

    for(auto x : v2)                        //foreach循环输出值
        std::cout << x << ",";

    typedef std::pair<int, std::string> pair_t;
    pair_t p(123, "string");

    std::cout << bind(&pair_t::first , p)() << std::endl;
    std::cout << bind(&pair_t::second, p)() << std::endl;

}

//////////////////////////////////////////

struct func
{
        int operator()(int a, int b)
            {   return a + b;   }
};

//绑定函数对象
void case4()
{
    bind(std::greater<int>(), _1, 10);
    bind(std::plus<int>(), _1, _2);
    bind(std::modulus<int>(), _1, 3);

    std::cout << bind<int>(func(), _1, _2)(10,20) << std::endl;
}

//配合 ref 库,免去了拷贝的代价
void case5()
{
    int x = 10;
    std::cout << bind(g,_1, cref(x), ref(x))(10) << std::endl;

    func af;
    std::cout << bind<int>(ref(af), _1, _2)(10, 20) << std::endl;


}

void case6()
{
    int x = 10;
    auto r = ref(x);
    {
        int *y = new int(20);
        r = ref(*y);

        std::cout << r << std::endl;
        std::cout << bind(g, r, 1, 1)() << std::endl;
        delete y;
    }
    std::cout << bind(g, r, 1, 1)() << std::endl;
}

#include <boost/rational.hpp>

//操作符重载
void case7()
{
    typedef rational<int> ri;
    std::vector<ri> v = {ri(1,2),ri(3,4),ri(5,6)};


    std::remove_if(v.begin(), v.end(), bind(&ri::numerator, _1) == 1 );
    assert(v[0].numerator() == 3);


    assert(std::find_if(v.begin(), v.end(), bind(&ri::numerator, _1) == 1) == v.end());

    auto pos = std::find_if(v.begin(), v.end(),
            bind(&ri::numerator, _1) >3 && bind(&ri::denominator, _1) < 8);

    std::cout << *pos << std::endl;

    pos = find_if(v.begin(), v.end(),
            [](ri &r)
            {
                return r.numerator() >3 && r.denominator() < 8;
            });
    std::cout << *pos << std::endl;
}

//lambda
void case8()
{
    auto lf = [](int x)
    {
        return f(x, 9);
    };

    assert(lf(10) == bind(f, _1, 9)(10));
}

int f(double a, double b)
{   return a * b;}

typedef int (*f_type1)(int, int);
typedef int (*f_type2)(double, double);

void case9()
{
    //std::cout << bind(f,1,2)() << std::endl;

    f_type1 pf1 = f;
    f_type2 pf2 = f;

    std::cout << bind(pf1,1,2)() << std::endl;
    std::cout << bind(pf2,1,2)() << std::endl;
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
    case8();
    case9();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# ./a.out 
3
7
10
7
30
30
30
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
0,0,0,0,0,0,0,0,0,0,123
string
30
110
30
20
21
1
5/6
5/6
3
2


function 是一个函数对象的"容器",概念上像是 c/c++ 函数指针类型的泛化,是一种"智能函数指针"。它以对象的形式封装了原始的函数指针或函数对象,可以被用于回调机制,暂时保管函数或函数对象,在之后需要的时机再调用,使回调机制拥有更多的弹性。

function 可以配合 bind/lambda 。function 可以容纳 0 到 10 个参数的函数,命名分别为 function0 - function10。

// Copyright (c) 2015
// Author: Chrono Law
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
//using namespace std;

#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace boost;

//////////////////////////////////////////

void case1()
{
    function<int()> func, func1;
    function<int (int  , int  , int   )>    func2;

    //func == func1;

    assert(func.empty());
    assert(!func);

    function0<int> func0;
    func0.clear();  //清空,等同于赋值0
    assert(!func0);
}

//////////////////////////////////////////

int f(int a, int b)
{   return a + b;}

void case2()
{
    //function<int(int,int)> func;
    function<decltype(f)> func;
    assert(!func);

    func = f;
    assert(func.contains(&f));

    if (func)
    {
        std::cout << func(10, 20) << std::endl;
    }

    func = 0;
    assert(func.empty());
}

//////////////////////////////////////////

struct demo_class
{
    int add(int a, int b)
    {       return a + b;   }
    int operator()(int x) const
    {       return x*x; }
};

void case3()
{
    function<int(demo_class&, int,int)> func1;

    func1 = bind(&demo_class::add, _1, _2, _3);

    demo_class sc;
    std::cout << func1(sc, 10, 20) << std::endl;
	
	//在bind是直接绑定类的实例
    function<int(int,int)> func2;

    func2 = bind(&demo_class::add,&sc, _1, _2);
    std::cout << func2(10, 20) << std::endl;

}

void case4()
{
    demo_class sc;
    function<int(int)> func;

    func = cref(sc);
    std::cout << func(10) << std::endl;
}

template<typename T>
struct summary
{
    typedef void result_type;
    T sum;

    summary(T v = T()):sum(v){}

    void operator()(T const &x)
    {   sum += x;   }
};

void case5()
{
    std::vector<int> v = {1,3,5,7,9};

    summary<int> s;
    function<void(int const&)> func(ref(s));

    std::for_each(v.begin(), v.end(), func);
    std::cout << s.sum << std::endl;
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# ./a.out 
30
30
30
100
25

function 非常适合代替函数指针,存储用于回调函数。

// Copyright (c) 2015
// Author: Chrono Law
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
//using namespace std;

#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace boost;


class demo_class
{
private:
    typedef function<void(int)> func_t;
    func_t func;
    int n;
public:
    demo_class(int i):n(i){}

    template<typename CallBack>
    void accept(CallBack f)
    {   func = f;   }

    void run()
    {   func(n);    }
};

void call_back_func(int i)
{
    using namespace std;
    cout << "call_back_func:";
    cout << i * 2 << endl;
}

void case1()
{
    demo_class dc(10);
    dc.accept(call_back_func);
    dc.run();

}

//传递对象,该对象重载了operator()
class call_back_obj
{
private:
    int x;
public:
    call_back_obj(int i):x(i){}

    void operator()(int i)
    {
        using namespace std;
        cout << "call_back_obj:";
        cout << i * x++ << endl;
    }
};

void case2()
{
    demo_class dc(10);
    call_back_obj cbo(2);

    dc.accept(ref(cbo));

    dc.run();
    dc.run();
}

//搭配bind
class call_back_factory
{
public:
    void call_back_func1(int i)
    {
        using namespace std;
        cout << "call_back_factory1:";
        cout << i * 2 << endl;
    }
    void call_back_func2(int i, int j)
    {
        using namespace std;
        cout << "call_back_factory2:";
        cout << i *j * 2 << endl;
    }
};

void case3()
{
    demo_class dc(10);
    call_back_factory cbf;

    dc.accept(bind(&call_back_factory::call_back_func1, cbf, _1));
    dc.run();

    dc.accept(bind(&call_back_factory::call_back_func2, cbf, _1, 5));
    dc.run();
}

//////////////////////////////////////////

bool case4()
{
    std::function<void(int)> func;

    func = call_back_func;

    //func.clear();
    //func.empty();

    return !!func;
}

int main()
{
    case1();
    case2();
    case3();
    case4();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# ./a.out 
call_back_func:20
call_back_obj:20
call_back_obj:30
call_back_factory1:20
call_back_factory2:100


 备注

1.编译器版本gcc4.8.5,运行环境centos7 64位
2.本文只做简单记录用,详细用法请参考 Boost Library,或者是罗剑锋的 boost程序库完全开发指南 书本
3..原文地址http://www.freecls.com/a/2712/b2


©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。