Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法
让你的函数对象可以与Boost.Lambda 一起使用
不是所有的表达式都适合使用 lambda 表达式,复杂的表达式更适合使用普通的函数对象,而且会多次重用的表达式也应该成为你代码中的一等公民。它们应该被收集为一个可重用函数对象的库。但是, 你也可能想把这些函数对象用在lambda 表达式中,你希望它们可以与 Lambda 一起使用;不是所有函数对象都能做到。问题是函数对象的返回类型不能象普通函数那样被推断出来;这是语言的固有限制。但是,有一个定义好的方法来把这个重 要的信息提供给Lambda 库,以使得 bind 表达式更加干净。作为这个问题的一个例子,我们看以下函数对象:
template <typename T> class add_prev {T prev_; public:add_prev() : prev_(0){}T operator()(T t) {prev_+=t;return prev_;} };
对于这样一个函数对象,lambda 表达式不能推断出返回类型,因此以下例子不能编译。
#include <iostream> #include <algorithm> #include <vector> #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" int main() {using namespace boost::lambda;std::vector<int> vec;vec.push_back(5);vec.push_back(8);vec.push_back(2);vec.push_back(1);add_prev<int> ap;std::transform(vec.begin(),vec.end(),vec.begin(),bind(var(ap),_1)); }
问题在于对 transform 的调用。
std::transform(vec.begin(),vec.end(),vec.begin(),bind(var(ap),_1));
当绑定器被实例化时,返回类型推断的机制被使用…而且失败了。因此,这段程序不能通过编译,你必须显式地告诉 bind 返回类型是什么,象这样:
std::transform(vec.begin(),vec.end(),vec.begin(),bind<int>(var(ap),_1));
这是为 lambda 表达式显式设置返回类型的正常格式的缩写,它等价于这段代码。
std::transform(vec.begin(),vec.end(),vec.begin(),ret<int>(bind<int>(var(ap),_1)));
template <typename T> class add_prev : public std::unary_function<T,T>
template <typename T> class add_prev :public std::unary_function<T,T> {T prev_; public:template <typename Args> class sig {public:typedef T type;}; // Rest of definition
模板参数 Args 实际上是一个 tuple,包含了函数对象(第一个元素)和调用操作符的参数类型。在这个例子中,我们不需要这些信息,返回类型和参数类型都是T. 使用这个改进版本的 add_prev,再不需要在 lambda 表达式中使用返回类型推断的缩写,因此我们最早那个版本的代码现在可以编译了。
std::transform(vec.begin(),vec.end(),vec.begin(),bind(var(ap),_1));
template <typename T> class sig_helper {}; // The version for the overload on int template<> class sig_helper<int> {public:typedef std::string type; }; // The version for the overload on std::string template<> class sig_helper<std::string> {public:typedef double type; }; // The function object class some_function_object {template <typename Args> class sig {typedef typename boost::tuples::element<1,Args>::typecv_first_argument_type;typedef typenameboost::remove_cv<cv_first_argument_type>::typefirst_argument_type;public:// The first argument helps us decide the correct versiontypedef typenamesig_helper<first_argument_type>::type type;};std::string operator()(int i) const {std::cout << i << '\n';return "Hello!";}double operator()(const std::string& s) const {std::cout << s << '\n';return 3.14159265353;} };
我们的函数对象可以在 lambda 表达式中正确使用是很重要的,在需要时定义嵌套sig 类是一个好主意;它很有帮助。
附代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
template <typename T>
class sig_helper {};
// The version for the overload on int
template<> class sig_helper<int> {
public:typedef std::string type;
};
// The version for the overload on std::string
template<> class sig_helper<std::string> {
public:typedef double type;
};
// The function object
class some_function_object {template <typename Args> class sig {typedef typename boost::tuples::element<1, Args>::typecv_first_argument_type;typedef typenameboost::remove_cv<cv_first_argument_type>::typefirst_argument_type;public:// The first argument helps us decide the correct versiontypedef typenamesig_helper<first_argument_type>::type type;};
public:std::string operator()(int i) const {std::cout << i << '\n';return "Hello!";}double operator()(const std::string& s) const {std::cout << s << '\n';return 3.14159265353;}
};
template <typename T, typename Operation>
void for_all(T& t, Operation Op) {std::for_each(t.begin(), t.end(), Op);
}
template <typename T>
void print(std::vector<T>& vec) {//using namespace boost::lambda;for_all(vec, std::cout << boost::lambda::_1 << '\n');
}
int main() {using namespace boost::lambda;{std::vector<std::string> vec;vec.push_back("my darling");vec.push_back("so sweet...");std::vector<double> vec2;vec2.push_back(1);vec2.push_back(2);some_function_object sfo;std::transform(vec.begin(),vec.end(),vec2.begin(),bind(var(sfo), _1));print(vec2);}{std::vector<std::string> vec;vec.push_back("my darling");vec.push_back("so sweet...");std::vector<int> vec2;vec2.push_back(1);vec2.push_back(2);some_function_object sfo;std::transform(vec2.begin(),vec2.end(),vec.begin(),bind(var(sfo), _1));print(vec);}
}
Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法相关推荐
- Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法 switch_statement
这些就是 if-then-else, 我们再看看 switch-语句,它与标准C++ switch有些不同. (switch_statement(_1,case_statement<0>( ...
- Linux环境高级编程函数,Linux环境高级编程--出错处理(CLStatus)
很多程序库对外提供若干类,每个方法出错时如何告知调用者是否出错,以及出错码(在Linux上在error.h中的全局errno就是保存我们Linux程序执行的出错码的)?方法很多,为了简化起见,函数将返 ...
- c#高级编程第11版 pdf网盘_c#高级编程_c#高级编程 目录 微盘_c#高级编程第10版 pdf...
c#高级编程 C#高级编程(第9版)-C# 5.0 & .NET 4.5.1是由.NET专家的梦幻组合编写,包含开发人员使用C#所需的所有内容.C#是编写.NET应用程序的一种语言,本书适合于 ...
- c语言前置函数,C语言高级编程-函数前置与后置调用
/ linux gcc下测试通过(有Bug请提交) 使用本代码需要注名作者: fqheda 本代码遵循GPL V3.0标准,可免费使用-- 函数前置与后置调用 注解:在同一个.c中,一个函数A调用另一 ...
- fork()函数_UNIX环境高级编程(APUE)系列学习第8章-2 exit系列函数与wait系列函数...
5 函数exit exit函数._exit函数和_Exit函数. 在7.3节中介绍了5中进程的正常终止和3种异常终止的方法. 但是无论进程如何终止,最后都会执行内核中的同一段代码.折断代码为相应进程关 ...
- 慕课网Flask高级编程实战-10.鱼书业务处理
10.1 最近的礼物 我们的首页会显示最近的赠送书籍列表.这个列表有三个限制条件: 1.数量不超过30 2.按照时间倒序排列,最新的排在最前面 3.去重,同一本书籍的礼物不重复出现 1.首先编写复杂S ...
- c++面向对象高级编程 总目录
本文是对学习侯捷视频 c++面向对象高级编程系列博客的目录总索引. c++面向对象高级编程 学习一 不带指针的类: 访问私有成员变量的方式,内联inline,常量成员函数,构造函数,值传递,引用传递, ...
- c++高级编程学习笔记5
multimap multimap 是一种允许多个元素使用同一个键的 map.和 map 一样,multimap 支持统一初始化.multimap的接口和 map 的接口几乎相同,区别在于multim ...
- 请问unix高级编程中的open包含哪些用法
"open" 在 Unix 高级编程中是指一个用于打开文件.设备和网络连接的系统调用.它的用法包括: 打开一个文件:通过 open 函数可以打开一个文件,并获取一个文件描述符. 设 ...
最新文章
- 系统学习Spring之Spring in action(二)
- OpenStack icehouse系列之计算节点搭建
- 新海诚没有参与制作的作品_新海诚作品不出真人版,其实都是因为这!
- 前端面试题及答案整理(一)
- 163邮箱有传真服务器,网易企业邮箱邮件传真功能使用说明
- B端产品经理需要着重锻炼自己这些能力
- dry的原理_速干面料的原理
- 连数据都读不懂,你凭什么说会数据分析?
- Ubuntu,kubuntu与xubuntu的差别 Ubuntu各版本主要差异
- Memcache架构新思考
- vue 判断权限过期_vue 路由权限
- leetcode *207. 课程表(拓补排序)(2020.8.4)
- C语言——判断一个数字是否为质数(素数)!
- 一文搞懂 RabbitMQ 延时队列(订单定时取消为例)
- 深度学习在OCR中的应用
- docker安装wechat微信、wxwork企业微信脚本整理
- 保利威视自定义右键菜单设置
- 格拉姆矩阵 Gram Matrix 简单理解
- 股票量化投资策略有哪些特点?
- 光伏行业报告:N型发展推动POE胶膜应用,POE产业链进入红利期
热门文章
- -32767转化为二进制_程序员需要了解的硬核知识之二进制
- asm 查看 数据文件 修改 时间_更高效的GMX分段模拟方法:修改tpr文件
- matlab 电气系统设计,MATLAB 简化了控制系统的设计和分析
- ART:分享收集的关于博物馆的视频纪录片,建议喜欢艺术人们的收藏
- 成功解决UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 130: invalid continuation b
- SQLServer之分离数据库
- 关于ML.NET v0.7的发布说明
- Linux系统新建用户用ssh远程登陆显示-bash-4.1$
- 内存不足导致mysql关闭,CentOS6.5增加swap分区
- 搜索打表大找规律 (hdu2045)