C++11函数绑定

函数绑定:

1.函数对象

(1.1)能够被当做函数调用的不一定就是函数,它们也可能是:

A.存放函数入口地址的函数指针

B.实现了小括号运算符的类对象,亦称仿函数

C.可被转换为函数指针的类对象

(1.2)可调用对象,像函数指针,仿函数以及可被转换为函数指针的类对象都被称为可调用对象,而他们的类型就被称为可调用类型

(1.3)函数对象,函数对象实际上是一个function类模板的实例化对象,其中封装了以上三种可调用对象的任何一种,

对函数对象的调用,实际就是对被其封装的可调用对象的调用

#include <iostream>
#include <functional>
using namespace std;

int fun(int x, int y)
{
    cout << __FUNCTION__ << endl;
    return x + y;
}

class Foo
{
public:
    Foo(void) {}
    Foo(int x, int y) :m_x(x), m_y(y) {}
    int operator()(int x, int y)const
    {
        cout << __FUNCTION__ << "1" << endl;
        return x + y;
    }
    int operator()(void)const
    {
        cout << __FUNCTION__ << "2" << endl;
        return m_x + m_y;
    }
private:
    int m_x, m_y;
};

class Bar
{
    //C++11通过using关键字给函数指针起别名
    using mfun_t = int(*)(int, int);
public:
    //operator隐式类型转换,函数指针也是一种类型
    operator mfun_t(void)const
    {
        return mfun;
    }
private:
    static int mfun(int x, int y)
    {
        cout << __FUNCTION__ << endl;
        return x + y;
    }

};

int add(int x, int y, function<int(int, int)>f)
{
    return f(x, y);
}

int main()
{
    //函数不是可调用的对象
    cout << fun(123, 456) << endl;
    //函数指针形式的可调用对象
    int(*pfunc)(int, int) = fun;
    cout << pfunc(123, 456) << endl;
    //仿函数形式的可调用对象
    Foo foo1;
    cout << foo1(123, 456) << endl;
    //cout << foo1.operator()(123,456) << endl;
    Foo foo2(123, 456);
    cout << foo2() << endl;
    //可被转换为函数指针的类对象形式的可调用对象
    Bar bar;
    cout << bar(123, 456) << endl;

    //function时一个模板,function<int(int,int)>表示接受两个int,返回一个int的可调用对象
    function<int(int, int)> f1 = pfunc;
    cout << f1(123, 456) << endl;
    function<int(int, int)> f2 = foo1;
    cout << f2(123, 456) << endl;
    function<int(int, int)> f3 = bar;
    cout << f3(123, 456) << endl;

    cout << add(111, 222, pfunc) << endl;
    cout << add(111, 222, foo1) << endl;
    cout << add(111, 222, bar) << endl;

    return 0;
}

2.函数绑定器

(2.1)函数绑定器可以将一个可调用对象和期望传递给该可调用对象的全部或者部分参数绑定为一个函数对象,

对该函数对象的调用就是在调用被其绑定的可调用对象。

函数对象 bind(可调用对象,期望参数表)

期望参数表可包含期望传递给可调用对象的0到多个参数

函数对象 <==> 可调用对象(期望参数表)

(2.2)placeholders::_n是一个占位符,其值将由传递给函数对象的第n个(从1开始算)参数取代。

#include <iostream>
#include <functional>
using namespace std;


int fun(int x, int y)
{
    cout << __FUNCTION__ << endl;
    return x + y;
}

class Foo
{
public:
    //重载()运算符
    int operator()(int x, int y)const
    {
        cout << __FUNCTION__ << endl;
        return x + y;
    }
};

class Bind
{
public:
    Bind(int(*pfunc)(int, int), int x, int y) :m_pfunc(pfunc), m_x(x), m_y(y) {}
    //重载()运算符
    int operator()(void)const
    {
        return m_pfunc(m_x, m_y);
    }

private:
    int(*m_pfunc)(int, int);
    int m_x;
    int m_y;
};

Bind myBind(int(*pfun)(int, int), int x, int y)
{
    return Bind(pfun, x, y);
}

int main()
{
    function<int(void)> f1 = bind(fun, 123, 456);
    cout << f1() << endl;
    cout << fun(123, 456) << endl;

    Bind f2 = myBind(fun, 123, 456);
    cout << f2() << endl;

    //placeholders定义在std命名空间中
    function<int(int)> f3 = bind(fun, 123, placeholders::_1);
    cout << f3(456) << endl;
    //function<int(int,int)> f4 = bind(fun, placeholders::_1,placeholders::_2);
    auto f4 = bind(fun, placeholders::_1, placeholders::_2);
    cout << f4(123, 456) << endl;

    auto f5 = bind(fun, placeholders::_5, placeholders::_3);
    cout << f5(1, 2, 3, 4, 5, 6, 7, 8, 9) << endl;
    //cout<<f5(5,3)<<endl;

    auto f6 = bind(Foo(), 111, 222);
    cout << f6() << endl;
    //cout<<Foo()(111,222)<<endl;

    using placeholders::_1;
    using placeholders::_2;

    auto f7 = bind(Foo(), _1, _2);
    cout << f7(444, 555) << endl;

    return 0;
}

3.无论类的普通成员函数还是静态成员函数,都可以通过bind与其参数一起绑定为函数对象,

但是要注意作为类的普通成员函数需要连同传递给它的this指针一起绑定。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

bool IsJige(int score)
{
    return score >= 60;
}

bool Compare(int num)
{
    return num > 30;
}

void test()
{
    vector<int> scores{ 60, 40, 50, 30, 80, 88, 85, 95, 10, 55,60 };
    //count函数返回元素值为target的元素个数,int num=count(vector1.begin(),vector2.begin(),target),注意不是vector的类函数
    int num = count(scores.begin(), scores.end(), 60);
    cout << num << endl;//2
    num = count(scores.begin(), scores.end(), 40);
    cout << num << endl;//1
    //count_if函数:返回符合一定条件的元素个数。compare()函数是自定义的,返回值是true就是表示符合要求
    vector<int> vi = { 10,20,30,40,50,60 };
    //返回大于30的个数
    num = count_if(vi.begin(),vi.end(),Compare);
    cout << num << endl;//3
}

int main()
{
    test();
    vector<int> scores{ 70, 40, 50, 30, 80, 88, 85, 95, 10, 55,60 };
    int jige = 0;
    for (auto score : scores)
        if (score >= 60)
            ++jige;
    cout << "及格:" << jige << endl;
    //count函数和count_if函数见test函数
    cout << "及格:" << count_if(scores.begin(), scores.end(), IsJige) << endl;
    //less_equal返回左边参数是否小于等于右边参数
    cout << boolalpha << less_equal<int>()(60, 60) << endl;//true
    cout << less_equal<int>()(60, 80) << endl;//true
    cout << less_equal<int>()(60, 30) << endl;//false
    //less返回左边参数是否小于右边参数
    cout << less<int>()(60, 60) << endl;
    using placeholders::_1;
    cout << "及格:" << count_if(scores.begin(), scores.end(), bind(less_equal<int>(), 60, _1));
    cout << "不及格:" << count_if(scores.begin(), scores.end(), bind(less<int>(), _1, 60));
    return 0;
}