boost--bind

Posted 一点一滴成长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了boost--bind相关的知识,希望对你有一定的参考价值。

1、bind1st和bind2end

  bind1st和bind2end是C++中的函数绑定器,它可以将一个变量绑定至一个二元函数对象,从而获得一个一元函数对象。使用需要包含头文件<functional>

  比如我们使用find_if()查找容器中大于100的元素,使用函数和函数对象的方法是如下:

技术分享
bool GreaterThan(const int& i)
{
    return i > 100;
}

class CGreaterThan
{
public:
    bool operator()(const int&i)
    {
        return i > 100;
    }
};

int main()
{
    vector<int> v = list_of(5) (2) (101) (3);
    auto iter = find_if(v.begin(), v.end(), /*GreaterThan*/CGreaterThan());
    if (iter != v.end())
        cout << *iter << endl;

    return 0;
}
View Code

   而使用函数绑定器的话就不用我们自定义函数或函数对象,如下所示:

技术分享
#include <functional>
int main()
{
    vector<int> v = list_of(5) (2) (101) (3);
    int x = 100;
    auto iter = find_if(v.begin(), v.end(), bind2nd(greater<int>(), x));
    if (iter != v.end())
        cout << *iter << endl;

    return 0;
}
View Code

  上面的bind2nd()将值100绑定到二元谓词greater<int>()的第二个参数,相当于将greater<int>()的第二个参数直接替换成了100,如果使用bind1st()的话就是将值绑定到第一个参数。

  not1和not2可以用来做否定值(not1是否定返回值是单目的函数,std中还有not2它是否定返回值是双目的函数),如以下就是获得小于等于100的元素:

技术分享
int main()
{
    vector<int> v = list_of(5) (2) (101) (3);
    auto iter = find_if(v.begin(), v.end(), not1(bind2nd(greater<int>(), 100)));
    if (iter != v.end())
    cout << *iter << endl;

    return 0;
}
View Code

 2、bind

  boost中的bind是bind1st/bind2nd的增强版,它也会返回一个函数对象,由于函数对象中重载了(),所以可以像函数一样来使用函数对象。bind()的第一个参数必须是一个可调用对象,比如函数、函数指针、函数对象,之后它最多接受九个参数。占位符用来表示使用哪一个参数。bind位于头文件"boost/bind.hpp"中。

  ①、绑定普通函数

技术分享
#include "boost/bind.hpp"

int func(int a, int b)
{
    return b * b;
}

int main()
{
    int x = 5, y = 10, z = 15;

    bind(func, x, y); //获得一个无参仿函数:绑定x到func第一个参数,绑定y到func第二个参数。bind(func, x, y)()相当与调用func(x, y)

    bind(func, x, _1); //获得带一个参数的仿函数:绑定x到func第一个参数,func第二个参数使用仿函数的第一个参数。bind(func, x, _1)(y)相当与func(x, y)

    bind(func, _1, y); //获得带一个参数的仿函数:绑定y到func第二个参数,func第一个参数使用仿函数的第一个参数。bind(func, _1, y)(x)相当与func(x, y)

    bind(func, _2, _1); //获得带两个参数的仿函数,func的第一个参数使用仿函数的第二个参数,func的第二个参数使用仿函数的第一个参数。bind(func, _2, _1)(x, y)相当于func(y, x)

    bind(func, x, _2); //获得带一个参数的仿函数:绑定x到func第一个参数,func第二个参数使用仿函数的第二个参数。bind(func, x, _2)(z, y)相当与func(x, y),参数z被忽略

    bind(func, _2, y); //获得带一个参数的仿函数:绑定y到func第二个参数,func第一个参数使用仿函数的第二个参数。bind(func, _2, y)(z, x)相当与func(x, y),参数z被忽略

    return 0;
}
View Code

  ②、绑定函数指针

  bind绑定函数指针与绑定普通函数方法相同。

  ③、绑定类的成员函数

  bind绑定类的public成员函数可以用来配合STL算法来操作容器中的对象,以下是使用bind与不使用bind完成对容器for_each()操作的比较:

技术分享
#include "boost/bind.hpp"

class CMyClass
{
public:
    void print()
    {
        cout << m_Value1 << ", " << m_Value2 << endl;
    }
private:
    int m_Value1 = 0, m_Value2 = 0;
};

void Print(CMyClass& c)
{
    c.print();
}

int main()
{
    vector<CMyClass> v(10);

    for_each(v.begin(), v.end(), /*Print*/bind(&CMyClass::print, _1));

    return 0;
}
View Code

  ④、绑定类的成员变量

  bind还可以绑定类的public成员函数,同样配合STL算法来操作容器中的元素,以下是使用bind与不使用bind完成对容器transform()操作的比较:

技术分享
#include "boost/bind.hpp"
class CPoint
{
public:
    int x = -1;
    int y = -1;
};

int assign(CPoint point)
{
    return point.x;
}

int main()
{
    vector<CPoint> inputV(10);
    vector<int> outputV(10);
    transform(inputV.begin(), inputV.end(), outputV.begin(), /*assign*/bind(&CPoint::x, _1));

    for (auto iter = outputV.begin(); iter != outputV.end(); iter++)
        cout << *iter << endl;

    return 0;
}
View Code

  ⑤、绑定函数对象

  bind绑定函数对象的时候需要在被绑定类中使用typedef来定义operator()返回值类型为result_type,否则在bind的时候还需使用<type>来指定类型。下面为使用count_if()算法来查找容器中元素长度小于5的个数,而count_if()使用的仿函数类型中

只有一个参数,可以使用两种方法来实现长度参数的传递:一种是将长度作为仿函数的构造函数的参数传入,一种是使用bind来获得一个参数的仿函数:

技术分享
#include "boost/bind.hpp"
class CLengthShorterThan
{
public:
    CLengthShorterThan(int len):m_len(len){}
    bool operator()(const string& str)
    {
        return str.length() < m_len;
    }
private:
    int m_len;
};

class CLenShorterThan
{
public:
    bool operator() (const string& str, int len)
    {
        return str.length() < len;
    }
    typedef bool result_type;
}; 

int main()
{
    vector<string> myVector = list_of("c++") ("c#") ("python");
    int len = 5;
    int count = count_if(myVector.begin(), myVector.end(), /*CLengthShorterThan(len)*/bind(CLenShorterThan(), _1, len));

    return 0;
}
View Code

  bind也可以绑定预定义的函数对象,如less<>、greater<>等。还可以使用BOOST_AUTO来存储bind表达式的结果,即保存bind返回的函数对象,以便使用。function库也可以存储bind表达式的结果。

技术分享
#include "boost/bind.hpp"
#include "boost/typeof/typeof.hpp"

int main()
{
    BOOST_AUTO(funObj, bind(greater<int>(), _1, _2));
    assert(funObj(2, 1));

    return 0;
}
View Code

 

以上是关于boost--bind的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::bind 有啥好处?

以boost::function和boost:bind取代虚函数

boost::bind 返回一个函数对象,它是需要指针的函数的参数

使用 boost::bind 将成员函数绑定到 boost::bisect?

使用 boost::bind 的调用错误没有匹配的函数

boost--bind