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

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. QT中视图(setViewport)和窗口(setWindow) 小总结

    参考博客: https://blog.csdn.net/weixin_39583140/article/details/92798127 https://blog.csdn.net/u01244271 ...

  2. linux根据进程名获取PID

    经常需要Kill多个进程,这些进程包含共同的关键字,可以用一条命令Kill掉它们. ps aux | grep "common" |grep -v grep| cut -c 9-1 ...

  3. nofollow标签的作用 nofollow标签添加方法

    这篇文章主要介绍了nofollow标签的作用 nofollow标签添加方法,需要的朋友可以参考下   nofollow标签的作用 nofollow标签添加方法  模拟搜狗蜘蛛   nofollow标签 ...

  4. HDU 6638 - Snowy Smile 线段树区间合并+暴力枚举

    HDU 6638 - Snowy Smile 题意 给你\(n\)个点的坐标\((x,\ y)\)和对应的权值\(w\),让你找到一个矩形,使这个矩阵里面点的权值总和最大. 思路 先离散化纵坐标\(y ...

  5. Delphi 自带了 Base64 编解码的单元

    Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因.  这个单元提供两套四个公开函数:  对流的编解码: procedu ...

  6. MySQL-初始化和自动更新TIMESTAMP和DATETIME

    https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html 例,添加自动更新的保存最后一次修改该条记录的时间戳的字段: ...

  7. laravel artisan工具的使用

    Artisan是laravel中自带的命令行工具的名称(一个php文件,放在laravel框架的根目录,因此命令的使用都是在根目录下的). 它提供了一些对应用开发帮助的命令,可以使用list命令列出所 ...

  8. Note1

    1.关于数据库主从备份与读写分离 主服务器数据库的每次操作都会记录在二进制日志文件mysql-bin.xxx中.从服务器的I/O线程使用专用帐号登陆到主服务器中读取该二进制文件,并将文件内容写入到自己 ...

  9. 11. Jmeter-后置处理器二

    jmeter-后置处理器介绍与使用二 今天我们接着讲 JSR223 PostProcessor Debug PostProcessor JDBC PostProcessor Result Status ...

  10. Html5 学习笔记 【PC固定布局】 实战7 机票预订页面

    最终实际效果: HTML代码: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta char ...