这次要讲的是:c++11中的bind和function

std::function

它是函数、函数对象、函数指针、和成员函数的包装器,可以容纳任何类型的函数对象,函数指针,引用函数,成员函数的指针。
以统一的方式处理函数、函数对象、函数指针、和成员函数。
允许保存和延迟执行函数。

  • 函数和成员函数作为function
void G();
struct A
{
void H(){}
}; std::function<void()> f = G; //全局函数 A a;
std::function<void()> f = 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%==)
f(x);
} void G(int x)
{
cout<<x<<endl;
} void H(int x)
{
cout<<x+<<endl;
} void TestFoo()
{
auto f = std::bind(G, std::placeholders::_1);
Foo(, f); //在Foo函数外面更改f的行为
f = std::bind(H, std::placeholders::_1);
Foo(, 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();
  • bind简化和增强bind1st和bind2nd

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

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

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

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

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

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

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

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

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

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

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

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

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

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

(原创)C++11改进我们的程序之简化我们的程序(五)的更多相关文章

  1. (原创)C++11改进我们的程序之简化我们的程序(八)

    本次要讲的是如何通过泛型函数来简化我们的程序. 泛型函数除了之前介绍的一些优点外还有两个重要的优点 1.消除重复逻辑,提高程序的内聚性和健壮性 泛型函数在某种程度上用来弥补泛型类型的不足.通过泛型类型 ...

  2. (原创)C++11改进我们的程序之简化我们的程序(二)

    这次要讲的是:C++11如何通过组合函数来简化我们的程序.关于组合函数,大家可能对这个概念有点陌生.组合函数是将N个一元函数组成一种更复杂的函数,每个函数的返回值作为参数传给下一个函数,直到传到最后一 ...

  3. C++11改进我们的程序之简化我们的程序1

    C++11改进我们的程序之简化我们的程序(一) C++11在很多方面可以简化我们的程序开发,我会在“简化我们的程序”这一系列的博文中一一讲到,敬请关注.这次要讲的是:C++11如何通过获取函数模板的返 ...

  4. (原创)C++11改进我们的程序之简化我们的程序(四)

    这次要讲的是:c++11统一初始化.统一begin()/end()和for-loop循环如何简化我们的程序 初始化列表 c++11之前有各种各样的初始化语法,有时候初始化的时候还挺麻烦,比较典型的如v ...

  5. (原创)C++11改进我们的程序之简化我们的程序(三)

    这次要讲的是:C++11如何通过auto.decltype和返回值后置来简化我们的程序. auto和c#中的var类似,都是在初始化时自动推断出数据类型.当某个变量的返回值难于书写时,或者不太确定返回 ...

  6. (原创)C++11改进我们的程序之简化我们的程序(一)

    C++11在很多方面可以简化我们的程序开发,我会在“简化我们的程序”这一系列的博文中一一讲到,敬请关注.这次要讲的是:C++11如何通过获取函数模板的返回值类型来简化我们的程序.在谈到简化之前,我们先 ...

  7. (原创)c++11改进我们的模式之改进代理模式,实现通用的AOP框架

    c++11 boost技术交流群:296561497,欢迎大家来交流技术. 本次要讲的时候如何改进代理模式,具体来说是动态代理模式,动态代理模式一般实现AOP框架,不懂AOP的童鞋看这里.我前面的博文 ...

  8. (原创)c++11改进我们的模式之改进命令模式

    模式虽然精妙,却难完美,比如观察者模式中观察者生命周期的问题:比如访问者模式中循环依赖的问题等等:其它很多模式也存在这样那样的一些不足之处,如使用场景受限.实现复杂.不够简洁.不够通用等.但我觉得不足 ...

  9. (原创)c++11改进我们的模式之改进访问者模式

    本次讲c++11改进我们的模式之改进访问者模式 访问者模式是GOF23个设计模式中比较复杂的模式之一,但是它的功能也很强大,非常适合稳定的继承层次中对象的访问,可以在不修改被访问对象的情况下,动态添加 ...

  10. (原创)C++11改进我们的程序之简化我们的程序(七)

    这次要讲的内容是:c++11中的tuple(元组).tuple看似简单,其实它是简约而不简单,可以说它是c++11中一个既简单又复杂的东东,关于它简单的一面是它很容易使用,复杂的一面是它内部隐藏了太多 ...

随机推荐

  1. UVA 10539 - Almost Prime Numbers(数论)

    UVA 10539 - Almost Prime Numbers 题目链接 题意:给定一个区间,求这个区间中的Almost prime number,Almost prime number的定义为:仅 ...

  2. Go map中一个很重要的特性

    先看一段代码: func main() { m := make(map[int]string) m[1] = "a" m[2] = "b" m[3] = &qu ...

  3. JavaScript escape() unescape() decodeURI()函数对字符串进行编码解码

    定义和用法 escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串. 语法 escape(string) 参数 描述 string 必需.要被转义或编码的字符串. 返回值 已 ...

  4. HDU 3980 Paint Chain (sg函数)

    Paint Chain Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. Maven学习--- 搭建多模块企业级项目

    我们先在eclipse中新建一个maven项目,pom.xml的文件如下: 搭建多模块项目,必须要有一个packaging为pom的根目录.创建好这个maven项目后,我们对着项目右键-->ne ...

  6. HTTP 请求头 Header

    HTTP 请求头 Header HTTP请求头概述 (HttpServletRequest) HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST或者HEA ...

  7. 【struts2】名为dispatcher的ResultType

    1)基本使用 名称为“dispatcher”的ResultType,在struts-default.xml里的配置如下: <result-type name="dispatcher&q ...

  8. [企业化NET]Window Server 2008 R2[2]-SVN 服务端 和 客户端 安装

    1.  服务器基本安装即问题解决记录      √ 2.  SVN环境搭建和客户端使用 2.1  服务端 和 客户端 安装    √ 2.2  项目建立与基本使用     √ 2.3  基本冲突解决, ...

  9. golang 学习笔记 ---内存分配与管理

    Go语言——内存管理 参考: 图解 TCMalloc Golang 内存管理 Go 内存管理 问题 内存碎片:避免内存碎片,提高内存利用率. 多线程:稳定性,效率问题. 内存分配   内存划分 are ...

  10. ef 通用类

    using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.I ...