std::function

它是函数、函数对象、函数指针、和成员函数的包装器,可以容纳任何类型的函数对象,函数指针,引用函数,成员函数的指针。

以统一的方式处理函数、函数对象、函数指针、和成员函数。

允许保存和延迟执行函数。

函数和成员函数作为function

void G();
struct A
{
void H(){}
}; std::function<void()> f = G; //全局函数 A a;
std::function<void()> f 1= std::bind(&A::H, a); //成员函数

可以用function取代函数指针。因为它可以保存函数延迟执行,所以比较适合作为回调函数,也可以把它看做类似于c#中特殊的委托,只有一个成员的委托。

struct A
{
A(std::function<void()>& f):m_callback(f)
void Notify()
{
m_callback();//回调到上层
} std::function<void()> m_callback;
}

function还可以作为函数入参,这样可以在函数外部控制函数的内部行为了,让我们的函数变得更加灵活。

void Foo(int x, std::function<void(int)>& f)
{
if(x%2==0)
f(x);
} void G(int x)
{
cout<<x<<endl;
} void H(int x)
{
cout<<x+2<<endl;
} void TestFoo()
{
auto f = std::bind(G, std::placeholders::_1);
Foo(4, f); //在Foo函数外面更改f的行为
f = std::bind(H, std::placeholders::_1);
Foo(4, f);
}

std::bind绑定器

将函数、成员函数和闭包转成function函数对象

将多元(n>1)函数转成一元函数或者(n-1)元函数。

void H(int a);
//绑定全局函数
auto f11 = std::bind(H, std::placeholders::_1);
auto的类型实际上是std::function<void(int)> //绑定带参数的成员函数
std::function<void (char*, int)> f = std::bind(&ReadHandler::ConnectPreProcess, this, std::placeholders::_1, std::placeholders::_1); //三元函数转换成一元函数
int f(int, char, double);
// 绑定f()函数调用的第二个和第三个参数,
// 返回一个新的函数对象为ff,它只带有一个int类型的参数
auto ff = bind(f, _1, ‘c’, 1.2);
int x = ff(7);

bind简化和增强bind1st和bind2nd

  其实bind简化和增强了之前标准库中bind1st和bind2nd,它完全可以替代bind1s和bind2st,并且能组合函数。我们知道bind1st和bind2nd将一个二元算子转换成一个一元算子。

  

//查找元素值大于10的元素的个数
int count = count_if(coll.begin(), coll.end(), std::bind1st(less<int>(), 10));
//查找元素之小于10的元素
int count = count_if(coll.begin(), coll.end(), std::bind2nd(less<int>(), 10));

 本质上是对一个二元函数less的调用,但是它却要分别用bind1st和bind2nd,而且还要想想到底是用bind1st还是bind2nd,用起来感觉不方便。现在用bind,就可以以统一的方式去实现了。

 

//查找元素值大于10的元素的个数
int count = count_if(coll.begin(), coll.end(), bind(less<int>(), 10, _1));
//查找元素之小于10的元素
int count = count_if(coll.begin(), coll.end(), bind(less<int>(), _1, 10));
这样我就不用关心到底是用bind1st还是bind2nd了,只要用bind就都搞定了。

bind函数组合

bind的还有一个强大之处就是函数组合。假设我们要找出集合中大于5小于10的元素个数怎么做呢?我们需要一个逻辑与才能做到类似于:

std::bind(std::logical_and<bool>(),_1,_2);

然后,我们需要另一个谓词来回答 _1 是否大于5。

std::bind(std::greater<int>(),_1,5);

然后,我们还需要另一个谓词来回答 _1 是否小于等于10。

std::bind(std::less_equal<int>(),_1,10);

最后,我们需要把它们两个用逻辑与合起来,就象这样:

//查找集合中大于5小于10的元素个数
auto f = bind(std::logical_and<bool>(), bind(std::greater<int>(),_1,5), bind(std::less_equal<int>(),_1,10));
int count = count_if(coll.begin(), coll.end(), f);

c++11中推出function是为了泛化函数对象,函数指针,引用函数,成员函数的指针,让我们可以按更统一的方式写出更加泛化的代码;推出bind是为了替换和增强之前标准库的bind1st和bind2st,让我们的用起来更方便!

(1)bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的

(2)对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的

(3)bind的返回值是可调用实体,可以直接赋给std::function对象

(4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的

(5)类的this可以通过对象或者指针来绑定

引用:http://www.cnblogs.com/qicosmos/p/3302144.html

最新文章

  1. Reporting Service 没有权限登陆
  2. (转载)完美解决PHP中文乱码问题
  3. 男装电商Bonobos融资5500万美元,计划IPO,全靠体验店战略 - 国外 - 快鲤鱼
  4. RTP 协议
  5. Winform中子线程访问界面控件时被阻塞解决方案
  6. Servlet中的过滤器Filter用法
  7. Struts+Spring+Hibernate、MVC、HTML、JSP
  8. SpringBoot简单打包部署(附工程)
  9. js/jQuery使用过程中常见问题/已踩过的坑大杂烩
  10. StackExchange.Redis .net core Timeout performing 超时问题
  11. vux环境配置
  12. SwipeRefreshLayout,用最少的代码定制最美的上下拉刷新样式
  13. lightoj1234 打表技巧:分块打表
  14. ElasticSearch文档及分布式文档存储
  15. 2017NOIP游记
  16. mysql 字符串数字转换
  17. Going Home
  18. ScrollView嵌套EditText联带滑动的解决的方法
  19. 23种设计模式之解释器模式(Interpreter)
  20. Freemarker简单用法

热门文章

  1. 虚拟化_Vmware——敬请期待!
  2. 一天五道Java面试题----第八天(怎么处理慢查询--------->简述Myisam和innodb的区别)
  3. Vulnhub 靶机 pwnlab_init 渗透——详细教程
  4. 在CentOS7下安装Oracle11教程
  5. Perl exists 函数和defined函数的区别
  6. 2022春每日一题:Day 35
  7. 推荐三个实用的 Go 开发工具
  8. gin领域层:用户实体编写和值对象(初步)
  9. MongoDB - 索引知识
  10. [ERROR] mariadbd: The table &#39;INNODB_BUFFER_PAGE&#39; is full