分享

C 11特性:bind和function函数使用

 印度阿三17 2020-12-06

目录

1. std::bind

2. std::function


1. std::bind

std::bind 的函数原型:

simple(1):
template <class Fn, class... Args>
  /* unspecified */ bind (Fn&& fn, Args&&... args);

with return type (2):
template <class Ret, class Fn, class... Args>
  /* unspecified */ bind (Fn&& fn, Args&&... args);

作用:返回基于fn的函数对象,但其参数绑定到args。

每个参数都可以绑定到一个值或占位符:

  • 如果绑定到一个值则调用返回的函数对象将始终使用该值作为参数。
  • 如果是一个占位符,则调用返回的函数对象会转发一个传递给调用的参数(该参数的顺序号由占位符指定)。

使用std::bind要注意的地方

  1. bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的。除非该参数被std::ref或者std::cref包装,才pass-by-reference。
  2. 对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;
  3. bind的返回值是可调用实体,可以直接赋给std::function对象; 
  4. 对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的;
  5. 类的this可以通过对象或者指针来绑定

测试程序:

#include <iostream>     // std::cout
#include <functional>   // std::bind

using namespace std;
// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide (double x, double y) {return x/y;}

struct MyPair {
  double a,b;
  double multiply() {return a*b;}
};

struct MyAdd {
  double add(int a,int b) {return a b;}
};

int main () {
  using namespace std::placeholders;    // adds visibility of _1, _2, _3,...

  // binding functions:
  auto fn_five = std::bind (my_divide,10,2);               // returns 10/2
  cout <<"fn_five(): "<<fn_five() << endl;                             // 5

  auto fn_half = std::bind (my_divide,_1,2);               // returns x/2
  cout <<"fn_half(10): "<< fn_half(10) << endl;                      // 5

  auto fn_invert = std::bind (my_divide,_2,_1);            // returns y/x
  cout <<"fn_invert(10,2): "<< fn_invert(10,2) << endl;                      // 0.2

  auto fn_rounding = std::bind<int> (my_divide,_1,_2);     // returns int(x/y)
  cout <<"fn_rounding(10,3): "<< fn_rounding(10,3) << endl;                   // 3

  MyPair ten_two {10,2};

  // binding members:
  auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
  cout <<"bound_member_fn():ten_two.multiply() "<< bound_member_fn(ten_two) << endl;           // 20

  auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
  cout <<"bound_member_data():ten_two.a "<< bound_member_data() << endl;                // 10
  
  MyAdd mAdd;
    
  auto bound_member_fn_add = std::bind (&MyAdd::add,&mAdd,_1,_2); // returns mAdd.add(_1,_2)
  cout <<"bound_member_fn_add(30,50): "<< bound_member_fn_add(30,50) << endl;           // 80

  return 0;
}

执行结果:

[root@192 function和bind函数学习]# ./bindTest
fn_five(): 5
fn_half(10): 5
fn_invert(10,2): 0.2
fn_rounding(10,3): 3
bound_member_fn():ten_two.multiply() 20
bound_member_data():ten_two.a 10
bound_member_fn_add(30,50): 80

2. std::function

类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、bind表达式、函数指针以及其它函数对象。std::function对象是对C 中现有的可调用实体的一种类型安全的包装(我们知道像函数指针这类可调用实体,是类型不安全的)。

通过std::function对C 中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象;让我们不再纠结那么多的可调用实体。

测试程序:

/**
 * 函数概述: std::function 是一种通用的多态函数包装器,可以存储、复制和调用任何可调用的目标——普通函数、
 * lambda表达式、bind表达式或其他函数对象,以及指向成员函数的指针和指向数据成员的指针(统称为“可调用对象”)。
 * 存在意义:多个不同类型的可调用对象却拥有着相同的调用形式。例如 std::function<int(int,int)>
 */

#include <functional>
#include <assert.h>
#include <iostream>

using namespace std;
 

/*加减乘除举例*/
typedef std::function<int(int,int)>  mFunctor;

int add(int a,int b)
{
    return a b;
}

struct sub
{
    int operator()(int a,int b)
    {
        return a-b;
    }
};

auto Lam = [](int a,int b)->int{return a*b;};

class Math
{
public:
    static int div(const int a, const int b)
    {
        assert(b);
        return a/b;
    }
int print_sum(int n1, int n2)
    {
        return n1 n2;
    }
};


int main()
{
    int a = 10, b = 5;
Math math;

    std::function<int(int,int)> fun1 = add;     //普通函数
    mFunctor fun2 = sub();//重载了函数调用运算符的函数对象
    mFunctor fun3 = Lam;      //lambada表达式
    mFunctor fun4 = Math::div;  //类静态成员函数
std::function<int(int,int)> fun5 = std::bind(&Math::print_sum, &math, std::placeholders::_1, std::placeholders::_2);//类成员函数

cout<<"fun1 add:"<<fun1(10,5)<<endl;
cout<<"fun2 sub():"<<fun2(10,5)<<endl;
cout<<"fun3 Lam:"<<fun3(10,5)<<endl;
cout<<"fun4 Math::div:"<<fun4(10,5)<<endl;
cout<<"fun5 Math::print_sum:"<<fun5(10,5)<<endl;
    return 0;
}

执行结果:

[root@192 function和bind函数学习]# ./functionTest
fun1 add:15
fun2 sub():5
fun3 Lam:50
fun4 Math::div:2
fun5 Math::print_sum:15

 

来源:https://www./content-1-776851.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多