函数对象是指那些可以被传入到其它函数或是从其它函数返回的一类函数。

1. boost::bind

bind提供了一个机制,是函数与几乎不限数量的参数一起使用,就可以得到指定签名的函数。bind会复制传递给它的参数。

#include <boost/bind.hpp>
#include <iostream>
#include <vector>
#include <algorithm> void add(int i, int j) {
std::cout << i + j << std::endl;
} int main() {
std::vector<int> v;
v.push_back();
v.push_back();
v.push_back(); std::for_each(v.begin(), v.end(), boost::bind(add, , _1)); return ;
}

add()函数要求两个参数,两个参数都必须传递给boost::bind()。第一个参数是10,第二个则是一个占位符,还有其他的占位符_2, _3。

使用这些占位符,boost::bind()可以变为一元、二元或三元的函数。对于_1,boost::bind()变成了一个一元函数,只需要一个参数的函数,而std::for_each()要求一个一元函数作为其第三个参数。程序执行,v中元素的值通过占位符_1传入到医院函数中,并进一步和常数一起传递到add()函数。通过这种机制,std::for_each()只看到了由boost::bind()定义的一元函数,而boost::bind()本身则是调用了另一个函数。

2. boost::ref

由于bind是复制传递给它的参数,如果参数为引用,则需要使用boost::ref(),boost::cref()

#include <boost/bind.hpp>
#include <iostream>
#include <vector>
#include <algorithm> void add(int i, int j, std::ostream& os) {
os << i + j << std::endl;
} int main() {
std::vector<int> v;
v.push_back();
v.push_back();
v.push_back(); std::for_each(v.begin(), v.end(), boost::bind(add, , _1, boost::ref(std::cout)));
}

3. boost::function

用来封装函数指针,

#include <boost/function.hpp>
#include <iostream>
#include <cstdlib>
#include <cstring> int main() {
boost::function<int (const char*)> f = std::atoi;
std::cout << f("") << std::endl; //调用atoi()
f = std::strlen;
std::cout << f("") << std::endl; //调用strlen()
return ;
}

boost::function可以定义一个指针,指向具有特定签名的函数。如上,定义了一个指针f,可以指向某个接受一个类型为const char*的参数且返回一个类型为int的值的函数。定义完成后,匹配此签名的函数均可赋值给这个指针呢。

若f未赋予一个函数而被调用,则会抛出一个boost::bad_function_call异常。若将0赋给一个boost::function类型的函数指针,将会释放所赋的函数。释放之后在调用也会导致boost::bad_function_call异常被抛出。要检查一个函数指针是否被赋予某个函数,可以使用empty()或operator bool()操作符。

#include <boost/function.hpp>
#include <iostream> struct world {
void hello(std::ostream& os) {
os << "Hello, world!" << std::endl;
}
} int main() {
boost::function<void (world*, std::ostrema&)> f = &world::hello;
world w;
f(&w, boost::ref(std::cout));
return ;
}

在调用这样的一个函数时,传入的第一个参数表示了该函数被调用的那个特定对象。因此,在模板定义中的左括号的第一个参数必须是该特定类型的指针,接下来的参数才是表示相应的成员函数的签名。

4. boost::lambda

匿名函数,可以使源代码更为紧凑。

#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <vector>
#include <algorithm> int main() {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3); std::for_each(v.begin(), v.end(), std::cout << boost::lambda::_1 << "\n");
return 0;
}

通过lambda::_1占位符,容器v的元素可以通过<<传给std::cout以将它们输出到标准输出。有一个例子:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/if.hpp>
#include <iostream>
#include <vector>
#include <algorithm> int main() {
std::vector<int> v;
v.push_back();
v.push_back();
v.push_bakc(); std::for_each(v.begin(), v.end(), boost::lambda::if_then(boost::lambda::_1 > , std::cout << boost::lambda::_1 << "\n"));
return ;
}

boost库:函数对象的更多相关文章

  1. boost库做什么用呢?

    1.C++标准库不是已经很全面了吗?Boost又不是界面库,它主要解决些什么问题呢?哪类问题?2.Boost的开发人员都是C++标准委员会的吧,为什么没把它列做标准库,有什么不完善的问题吗? 3.Bo ...

  2. boost库在工作(15)绑定器与函数对象之三

    前面已经可以优美地解决两个参数的函数给算法for_each调用了,但是又会遇到这样的一种情况,当需要三个参数或者三个以上的参数给算法for_each调用呢?从STL里的绑定器bind1st,显然是不行 ...

  3. C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象

    函数调用运算符 struct test { int operator()(int val) const { return (i > 0 ? i : -i); } }; 所谓的函数调用就是一个类重 ...

  4. 【实习记】2014-08-15文档太少看着源码用cgicc+stl库之模板谓词函数对象

        总结1: 今天找到了昨天scanf的问题答案,scanf与printf一样的神奇而复杂,稍不留神,就会被坑.scanf函数在读入非空白符分割的多个字符串的解决方法是这个:/* 以 | 分割 * ...

  5. 8、泛型程序设计与c++标准模板库5.函数对象

    1.函数对象 函数对象是STL提供的第四类主要组件,它使得STL的应用更加灵活方便,从而增强了算法的通用性.大多数STL算法可以用一个函数对象作为参数.所谓“函数对象”其实就是一个行为类似函数的对象, ...

  6. [C/C++] C/C++延伸学习系列之STL及Boost库概述

    想要彻底搞懂C++是很难的,或许是不太现实的.但是不积硅步,无以至千里,所以抽时间来坚持学习一点,总结一点,多多锻炼几次,相信总有一天我们会变得"了解"C++. 1. C++标准库 ...

  7. C++ | boost库 类的序列化

    是的,这是今年的情人节,一篇还在研究怎么用的文章,文结的时候应该就用成功了. 恩,要有信心 神奇的分割线 不知何时装过boost库的header-only库, 所以ratslam中的boost是可以编 ...

  8. boost库(条件变量)

    1相关理念 (1)类名 条件变量和互斥变量都是boost库中被封装的类. (2)条件变量 条件变量是thread库提供的一种等待线程同步的机制,可实现线程间的通信,它必须与互斥量配合使用,等待另一个线 ...

  9. boost库----enable_shared_from_this类的作用和实现原理

    使用boost库时,经常会看到如下的类 class A:public enable_share_from_this<A> 在什么情况下要使类A继承enable_share_from_thi ...

  10. Boost库

    2014-08-31 Boost库是一个经过千锤百炼.可移植.提供源代码的C++库,作为标准库的后备,是C++标准化进程的发动机之一.Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成 ...

随机推荐

  1. ExtJS5.0 菜鸟的第一天

    1.新项目开始啦,后台用户管理页面涉及到表格数据添加,修改内容比较多.准备用EXTJS框架搞下,对于我这种JS不咋地的人来说,还真是个挑战.整了2天,才搞出一个Hello,world!我也是醉了.. ...

  2. bootstrap响应式布局原理

    百分比布局+媒体查询 首先通过媒体查询确认container的宽度,每个col-xx-xx都是通过百分比定义的,屏幕尺寸变化了,container就变化了,col自然就变了 Bootstrap的官方解 ...

  3. tab切换中的滚动条下拉分页带来的问题

    相信做过tab切换中滚动条下拉分页的童鞋都知道,我们在用scroll方法来做滚动条下拉分页的时候,都是有bug,切换中间的内容会互相影响,为了解决这个问题,我总结了2种方法: 1.方法一: <! ...

  4. 多任务Multitask Learning

    一次只学习一个任务,大部分机器学习都属于单任务学习. 多任务学习:把多个相关的任务放在一起学习,同时学习多个任务. 对于复杂的问题,可以分解为简单的相互独立的子问题来解决,然后再合并结果,得到最初复杂 ...

  5. blob格式导出文件

    最近在做blob流导出相关功能,其中需要导出excel.csv.word.zip压缩文件之类的,在导出excel和word中需要知道对应的content-type属性,正好看到下面这篇文章,感觉挺好的 ...

  6. PHP之面向对象小结

    PHP 中创建对象 类创建后,我们可以使用 new 运算符来实例化该类的对象: $runoob = new Site; PHP 构造函数 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, ...

  7. SQL案例

    1.字符串去掉空格 原因:(1)空格 (2)制表符 )); ); ); INSERT INTO #temp SELECT '明天我就结婚了 '; DROP TABLE #temp; --1.2 采用A ...

  8. UITableView 支持左右滑动(二)

    原理: 用tableView其中一个cell 来展示一个 UIScrollView, 在scrollview上很像放置子tableView 注意点: 外层tableView需要实现手势代理 /* 若重 ...

  9. ssd存储的SLC、MLC、TLC闪存芯片颗粒有什么区别?

    SLC = Single-Level Cell ,即1bit/cell,速度快寿命长,价格贵(约MLC 3倍以上的价格),约10万次擦写寿命: MLC = Multi-Level Cell,即2bit ...

  10. python 装饰器 第一步:基本函数

    # 第一步:基本函数 def eat(): print('吃饭') # 调用 eat()