lambda是一种语法糖。lambda可以在函数内定义,可以匿名,甚至可以在定义的地方原地执行,所以也就可以很方便的放置到代码中。通常我们自上而下写代码逻辑,可以在需要一个函数的时候(比如需要一个Callback)原地定义一个lambda对象,而不需要移动光标到函数体外去定义一个函数或struct。这些都是从“简化代码”、“语法糖”角度来谈及的lambda优势,我也不再赘述

今天我想讲的是lambda搭配宏定义产生的一些化学反应,这些功用在lambda出现以前很难用简便的方法实现相同效果

在某个场景中,我需要把回调函数和某个字符串注册进一个map,后续通过字符串查找来回调执行指定的函数。

这个确实稀松平常,大家稍安勿躁。假设我们是从Redis或者其他KV中用key来查value,然后解析value做一些操作,但对不同key的value的处理操作有比较相似。

先看下这个例子初版代码:

#include <iostream>
#include <functional>
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/algorithm/string.hpp>using namespace std;
struct ServiceData{vector<string> aaa_value_list;vector<string> bbb_value_list;vector<string> ccc_value_list;vector<string> ddd_value_list;// 十几个不同的value_list...
};class Service {using callback_t = function<int(const string&, ServiceData&)>;
public:static Service& instance() {static Service ins;return ins;}int run(ServiceData&); // 具体业务逻辑,其中会使用到回调函数void set_callback(const string& key, callback_t callback) {cb_map.emplace(key, callback);}private:Service();Service(const Service&) = delete;unordered_map<string, callback_t> cb_map;
};Service::Service() {set_callback("aaa", [](const string& data, ServiceData& sd) {// 解析data , 具体处理boost::split(sd.aaa_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});set_callback("bbb", [](const string& data, ServiceData& sd) {// 解析data , 具体处理boost::split(sd.bbb_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});set_callback("ccc", [](const string& data, ServiceData& sd) {// 解析data , 具体处理boost::split(sd.ccc_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});set_callback("ddd", [](const string& data, ServiceData& sd) {// 解析data , 具体处理boost::split(sd.ddd_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});// ... 注册十几个}

OK,我们发现每个回调函数里面结构基本一致的,但是涉及的变量不同,但变量命名和key相关。所以我们很容易想到将写一个函数宏来简化之。

#define SET_CB(key) \set_callback(#key, [](const string& data, ServiceData& sd) { \boost::split(sd.key##_value_list, data, boost::is_any_of(","), boost::token_compress_on); \return 0; \}); \Service::Service() {SET_CB(aaa)SET_CB(bbb)SET_CB(ccc)SET_CB(ddd)// ... 注册十几个}

OK ,到这里其实依旧稀松平常,不够惊艳。下面重点来啦。后来呢,我想统计一下key查询的成功率,这里方便demo直观演示就简单处理,将data为空字符串视为key处理失败

我并不关心是具体是哪个key成功了,哪个key失败了。我只关心查询成功的key数量。

所以我弄了一个bitset,每一位用0/1表示成功与否:

struct ServiceData{bitset<20> suc_bit;vector<string> aaa_value_list;vector<string> bbb_value_list;vector<string> ccc_value_list;vector<string> ddd_value_list;// 十几个不同的value_list...
};

bitset初始化默认为0,我们只需要在成功的时候标记上1即可。

Service::Service() {set_callback("aaa", [](const string& data, ServiceData& sd) {if (data.empty()) {return -1;}sd.suc_bit[0] = 1;// 解析data , 具体处理boost::split(sd.aaa_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});set_callback("bbb", [](const string& data, ServiceData& sd) {if (data.empty()) {return -1;}sd.suc_bit[1] = 1;// 解析data , 具体处理boost::split(sd.bbb_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});set_callback("ccc", [](const string& data, ServiceData& sd) {if (data.empty()) {return -1;}sd.suc_bit[2] = 1;// 解析data , 具体处理boost::split(sd.ccc_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});set_callback("ddd", [](const string& data, ServiceData& sd) {if (data.empty()) {return -1;}sd.suc_bit[3] = 1;// 解析data , 具体处理boost::split(sd.ddd_value_list, data, boost::is_any_of(","), boost::token_compress_on);return 0;});// ... 注册十几个
}

每个key占用一位,且必须不同。在每个key的回调函数都执行完毕后,调用sb.suc_bit.count()统计1的个数也就是成功的key的个数。

这个用函数宏怎么实现呢。我们的SET_CB该如何改造?简单的实现是这样,但是太丑了:

#define SET_CB(key, i) \set_callback(#key, [](const string& data, ServiceData& sd) { \if (data.empty()) { \return -1; \} \sd.suc_bit[i] = 1; \boost::split(sd.key##_value_list, data, boost::is_any_of(","), boost::token_compress_on); \return 0; \}); \Service::Service() {SET_CB(aaa, 0)SET_CB(bbb, 1)SET_CB(ccc, 2)SET_CB(ddd, 3)// ... 注册十几个}

你要自己传入1,2,3,4……,还不能出错。能不能不要自己传入这个,但是还能让表示bitset下标的数字自增呢?

能啊,别忘了,lambda有捕获功能!

#define SET_CB(key) \set_callback(#key, [keyi](const string& data, ServiceData& sd) { \if (data.empty()) { \return -1; \} \sd.suc_bit[keyi] = 1; \boost::split(sd.key##_value_list, data, boost::is_any_of(","), boost::token_compress_on); \return 0; \}); \keyi++;Service::Service() {int keyi = 0;SET_CB(aaa)SET_CB(bbb)SET_CB(ccc)SET_CB(ddd)// ... 注册十几个}

重点:今天想讲的就是最后这个代码片段。

有帮到你的点赞、收藏一下吧

需要更多教程,微信扫码即可

Lambda 的优势相关推荐

  1. 快用一用 lambda 表达式吧,让你的代码更简洁、更漂亮!

    目录 lambda 表达式 定义 lambda 表达式 捕获子句 按值捕获 按引用捕获 捕获特定的变量 捕获this指针 结合 lambda 使用 STL 算法 lambda 表达式 lambda 表 ...

  2. 一文看懂当红Serverless:为何AWS、阿里云和腾讯云都在发力「无服务器架构」

    冠望 发自 凹非寺 量子位 报道 | 公众号 QbitAI 要说目前软件架构中热度十二分的话题,当属Serverless. 通常我们会将其翻译为"无服务器架构". 尽管成天被称为& ...

  3. 转使用Moq让单元测试变得更简单

    [ASP.Net MVC3 ]使用Moq让单元测试变得更简单 前几天调查完了unity.现在给我的任务是让我调查Moq. 以下是自己找了资料,总结并实践的内容.如果有表述和理解错误的地方.恳请指正. ...

  4. 《Effective Modern C++》笔记

    文章目录 绪论 第1章 型别推导 条款1:理解模板类型推导 情况1:ParamType 是个指针或引用,但不是万能引用 情况2:ParamType是万能引用 情况3:ParamType既非指针也非引用 ...

  5. c#服务器后端_一文看懂Serverless:AWS阿里云腾讯云都在发力「无服务器架构」

    冠望 发自 凹非寺 量子位 报道 | 公众号 QbitAI 要说目前软件架构中热度十二分的话题,当属Serverless. 通常我们会将其翻译为"无服务器架构". 尽管成天被称为& ...

  6. 【ASP.Net MVC3 】使用Moq让单元测试变得更简单

    前几天调查完了unity.现在给我的任务是让我调查Moq. 以下是自己找了资料,总结并实践的内容.如果有表述和理解错误的地方.恳请指正. 什么是Moq? Moq(英语发音是Mock-you 或者只是m ...

  7. 一起谈.NET技术,从.NET中委托写法的演变谈开去(中):Lambda表达式及其优势...

    在上一篇文章中我们简单探讨了.NET 1.x和.NET 2.0中委托表现形式的变化,以及.NET 2.0中匿名方法的优势.目的及注意事项.那么现在我们来谈一下.NET 3.5(C# 3.0)中,委托的 ...

  8. 从.NET中委托写法的演变谈开去(中):Lambda表达式及其优势

    在上一篇文章中我们简单探讨了.NET 1.x和.NET 2.0中委托表现形式的变化,以及.NET 2.0中匿名方法的优势.目的及注意事项.那么现在我们来谈一下.NET 3.5(C# 3.0)中,委托的 ...

  9. Python 精选笔试面试习题—sorted 与 sort 单例模式、统计字符个数Count、垃圾回收、lambda函数、静态方法、类方法、实例方法、分布式锁、

    1. 字典根据键从小到大排序? In[38]: dic = {"name": "Tom", "age": 30, "country ...

最新文章

  1. 宁德时代机器人编程开发_全球首例丨可编程的活体机器人已诞生,100%青蛙基因,超级计算机时代,将无所不能?!...
  2. 非负矩阵分解中基于L1和L2范式的稀疏性约束
  3. python怎么按键开始与停止_使用Python启动和停止子流程
  4. 【Python】Python“表情包”工具包真好用
  5. 素性测试的Miller-Rabin算法完全解析 (C语言实现、Python实现)
  6. bat递归查找指定文件_批处理脚本遍历指定文件夹下的文件
  7. ubuntu命令和配置文件 修改IP
  8. async与await详解
  9. 关于架设流媒体服务器与DRM加密问题
  10. java 内存泄漏问题_Java内存泄露的理解与解决(转)
  11. BP神经网络python代码实现
  12. ocx注册方法,vs安装包自动安装ocx,以及ocx注册失败的解决方法
  13. qq服务器上的文件删除后如何恢复,QQ文件失效怎么恢复(过期的QQ文件如何申请恢复)...
  14. tp1900芯片对比7621a_MT7621A /MT7620N / MT7620A单频双频刷机教程(区别于高通芯片刷机过程)...
  15. 全媒舍:活动策划的几个要点与常用做法
  16. jmeter性能测试1-录制脚本
  17. GDUT 2.25 D
  18. 三无真香级浏览器——Alook
  19. LOL服务器维护奖励,LOL5.18版本改动内容 lol官网服务器维护公告
  20. 基于Spring事件模型实现观察者模式的工程实践

热门文章

  1. 堪称奇迹!8 天诞生一个产品,这家创业公司做到了
  2. 奥迪公布未来五年计划:将在电动汽车方面投资120亿欧元
  3. 英特尔西安团队将被裁撤 波及约200人?回应...
  4. iQOO高层专访:打造性能旗舰 用户满意度为先
  5. 2018年小米竟发布了16款手机,然而最值得入手的是它!
  6. 女儿是程序员爸爸的小棉袄,礼物太暖心
  7. Linux的shell编程(一)
  8. 在相册查看保存的图片
  9. 【scrapy】学习Scrapy入门
  10. 智能控制第四版程序代码_晋中成本低的智能水表方便了人们生活