C++高级特性:柯里化过程与std::bind(六)

1、柯里化过程
1.1、operator()的引入

现在需要完成这样一个需求:有一个函数每次调用返回的结果不一样。例如:两次调用的返回值都不一样那么就可以达到这种目的

1.1.1、简单点的写法

可以给一个全局的变量(静态变量),每次调用对这个全局变量进行值的修改然后返回,这样每次返回都不一样。

#include <iostream>
int nums;
int func()
{return ++nums;
}int main() {std::cout << "Hello, World!" << std::endl;std::cout << std::boolalpha << (func() == func()) << std::endl;return 0;
}
1.1.2、operator()重载

如果需要用类来完成,那么可以使用operator()仿函数来做,仿函数其实是一个特殊的函数。

class Functor{
public:int x;int operator()(){return ++x;}
};
void test2()
{Functor func;std::cout << std::boolalpha << (func() == func()) << std::endl;
}
1.2、Chain Adding

有了上面的基础,可以看这样一个题目:

  • 打算创建一个函数,这个函数能够完成类似于add(1) = 1、add(1)(2) = 3、add(1)(2)(3) = 6…类似于这种求和的操作。
  • 并且能够判断出add(1) == 1这种判断也能完成,以及add(1) + 3、add(1) - 3
  • 意思没出现一个括号就会对之前的值进行一个加法和减法

通过分析可以看到add(1)应该返回一个类似函数的东西func,然后这个东西还可以继续func(2)…可以尝试使用上面的仿函数来继续,

  • 很明显这里有一个链式编程的东西,返回的东西应该是一个类对象本身的引用这样就可以继续链式,当然也可以返回一个普通类型但是要做好拷贝构造。
  • 对于不同类型的比较,那么肯定需要重载一下==符号进行判断值是否相等即可。
  • 对于第三个操作很明显需要重载加减法么,一样需要注意返回引用或者拷贝构造的对象。
  • 思考:如果需要流输出类对象应该怎么做呢?答案:重载输出流
  • 补充:其实还可以把类型进行重载,把当前类中的返回类型重载为int可以直接省略判断、加减和输出操作
class Functor{
public:int sum;Functor(): sum(0){}Functor(int x): sum(x){}Functor& operator()(int val){this->sum += val;return *this;}bool operator== (const int x) const{return sum == x;}Functor& operator-(int x){this->sum -= x;return *this;}Functor& operator+(int x){this->sum += x;return *this;}friend std::ostream & operator<<(std::ostream& out, const Functor& functor){out << functor.sum << std::endl;return out;}
//    operator int() {							//可以直接替换 == 重载、 加减法、输出流
//        return this->sum;
//    }
};int main()
{Functor f1;f1(1);std::cout << f1.sum << std::endl;Functor f2;f2(1)(2);std::cout << f2.sum << std::endl;Functor f3;std::cout << std::boolalpha << (f3(1) == 1)<< std::endl;Functor f4(1);f4 = f4 - 2;f4 = f4 + 5;std::cout << f4.sum << std::endl;std::cout << f4 << std::endl;return 0;
}

其实这是一个很好的例子,可以帮助我们理解重载的意义和C++面向对象的灵活使用。

1.3、柯里化过程

其实上面的链式编程或者函数式编程就是一个柯里化的过程,其实这种操作在lambda表达式也有体现的,lambda表达式中继续lambda表达式

// add(1, 2)     -->   add(1)(2)
void test4()
{auto add = [](int x)->auto{return [x](int y) -> auto{return x + y;};};std::cout << add(1)( 2) << std::endl;
}
2、std::bind
  • 有了上面函数式编程和柯里化的过程,理解bind就很简单了。
  • std::bind主要用于给函数进行参数绑定的
#include <iostream>
#include <functional>int add(int a, int b)
{std::cout << "a = " << a << ", b = " << b <<std::endl;return a + b;
}
int main()
{using namespace std::placeholders;auto f1 = std::bind(add, 1, _1);std::cout << f1(2) << std::endl;auto f2 = std::bind(add, _1, 1);std::cout << f2(2) << std::endl;std::cout << std::bind(add, 1, _1)(2) << std::endl;std::cout << std::bind(add, _1, _2)(3, 4) << std::endl;std::cout << std::bind(add, _2, _1)(3, 4) << std::endl;std::cout << std::bind(add, _1, _1)(3, 4) << std::endl;std::cout << std::bind(add, _2, _2)(3, 4) << std::endl;// C++20标准
//    std::cout << std::bind_front(add, 1)(2) << std::endl;// C++23标准
//    std::cout << std::bind_back(add, 2)(1) << std::endl;return 0;
}

在这里插入图片描述

  • 为了给bind参数绑定需要引入命名空间中的using name std::placeholders占位符宏
  • 通过_i来表示第几个参数,其中最明显的是一绿框和黑框中的
    • 绿框:根据传入的占位符宏的编号索引到对应的值,_2表示取参数列表的第2个参数、依次类推
    • 黑框:当参数列表为X个时,可以使用的宏为_i <= X,同时可以多个参数绑定同一个宏
  • 和std::move一样可能现在对这个概念还不是很熟悉,等到完美转发forward的时候会更加清楚的理解bind和move

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/810914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java项目两种方法实现大批量数据:存在就更新,不存在就新增,脏数据就删除。

java项目两种方法实现大批量数据&#xff1a;存在就更新&#xff0c;不存在就新增&#xff0c;脏数据就删除。 文章目录 java项目两种方法实现大批量数据&#xff1a;存在就更新&#xff0c;不存在就新增&#xff0c;脏数据就删除。一、法一&#xff1a;存在就更新&#xff0c;…

Docker 安装Kali Linux作为攻防演练的工具

使用Docker Compose安装和运行Kali Linux是一种简便且灵活的方式&#xff0c;特别适合那些希望在隔离环境中快速部署和管理多个Docker容器的用户。以下是详细的步骤&#xff0c;包括如何设置Docker Compose文件来运行Kali Linux&#xff1a; 步骤 1: 安装Docker 如果你的系统…

深入理解JVM垃圾收集器

相关系列 深入理解JVM垃圾收集算法-CSDN博客 目前市面常见的垃圾收集器有Serial、ParNew、Parallel、CMS、Serial Old、Parallel Old、G1、ZGC以及有二种不常见的Epsilon、Shenandoah的&#xff0c;从上图可以看到有连线的的垃圾收集器是可以组合使用&#xff0c;是年轻代老年代…

[NOIP2000 提高组] 单词接龙

[NOIP2000 提高组] 单词接龙 题目背景 注意&#xff1a;本题为上古 NOIP 原题&#xff0c;不保证存在靠谱的做法能通过该数据范围下的所有数据。 本题为搜索题&#xff0c;本题不接受 hack 数据。关于此类题目的详细内容 NOIP2000 提高组 T3 题目描述 单词接龙是一个与我…

【搜索算法】靠item标签召回,超越ElasticSearch+分词的baseline

要超越ElasticSearch&#xff08;item名&#xff09;分词的baseline&#xff0c;如果都要求 有相关性的item&#xff08;有token匹配&#xff09;&#xff0c;其实就是相当于优化分词&#xff0c;而分词优化的极限就是把 item名和query词 切分成字级token。 所以标签召回&…

Input DropDown 拼接成 select组件(基于antd和react)

前言&#xff1a;为什么不直接用select&#xff0c;还要舍近求远搞inputdropdown这种缝合怪&#xff0c;是因为antd的select不支持选中项再编辑&#xff0c;效果如图 比如&#xff1a;选中的lucy文案变成了placeholder不能再编辑了 封装此组件虽然比较简单&#xff0c;但还是有…

C++中的for循环

上一讲C的输入输出与判断经过练习&#xff0c;就可以写简单的程序了。但是在信奥赛中&#xff0c;几乎没有不需要使用循环的。因此&#xff0c;循环是C的一门必学课。 时间复杂度 时间复杂度是初赛中一个重要的考点。何为时间复杂度&#xff1f;就是程序执行语句的速度。带有…

PLC互连全攻略:Profinet和EthernetIP实操演示

在今日的技术分享中&#xff0c;将详细探讨实现Profinet和Ethernet/IP的通信配置&#xff0c;以连接西门子PLC&#xff08;Profinet&#xff09;和罗克韦尔PLC&#xff08;Ethernet/IP&#xff09;。本篇将重点介绍专为通信而设计的Profinet转Ethernet/IP网关&#xff0c;在联接…

ActiveMQ介绍及linux下安装ActiveMQ

ActiveMQ介绍 概述 ActiveMQ是Apache软件基金下的一个开源软件&#xff0c;它遵循JMS1.1规范&#xff08;Java Message Service&#xff09;&#xff0c;是消息队列服务&#xff0c;是面向消息中间件&#xff08;MOM&#xff09;的最终实现&#xff0c;它为企业消息传递提供高…

Linux命令学习—linux 下的用户和组的管理(上)

1.1、linux 系统下用户角色 在 linux 系统下用户的角色不同&#xff0c;权限和所能完成的任务也不同&#xff0c;用户角色是通过 UID 来识别的&#xff0c; 注意&#xff1a;在 linux 下要注意 root 用户的 UID 的唯一性。 ①、Root 系统管理员超级用户&#xff0c;系统唯一&a…

C#-MemoryMarshal

MemoryMarshal 类是 .NET 中用于处理内存的工具类&#xff0c;它提供了一组静态方法&#xff0c;用于在托管代码中以安全和高效的方式操作内存块。MemoryMarshal 类主要用于处理原始内存数据而不需要进行复制&#xff0c;这对于性能关键的操作非常有用。 MemoryMarshal 类包含…

【R语言从0到精通】-3-R统计分析(列联表、独立性检验、相关性检验、t检验)

上两次教程集中学习了R语言的基本知识&#xff0c;那么我们很多时候使用R语言是进行统计分析&#xff0c;因此对于生物信息学和统计科学来说&#xff0c;R语言提供了简单优雅的方式进行统计分析。教程参考《Rlearning》 3.1 描述性统计分析 3.1.1 载入数据集及summary函数 我…

【力扣题】关于单链表和数组习题

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

(Java)数据结构——图(第五节)Kruskal的实现最小生成树(MST)

前言 本博客是博主用于复习数据结构以及算法的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 Kruskal算法&#xff08;Kruskal的实现原理&#xff09; Kruskal算法的原理&#xff1a; 就是每次取最小的边&#xff0c;看看是不是与已经选择的构成回路&#x…

金融机构面临的主要AI威胁:身份伪造统与社会工程攻击

目录 攻击者利用AI威胁的过程 金融机构如何防范AI攻击 针对AI欺诈的解决方案 2023年11月&#xff0c;诈骗分子伪装成某科技公司郭先生的好友&#xff0c;骗取430万元&#xff1b;2023年12月&#xff0c;一名留学生父母收到孩子“被绑架”的勒索视频&#xff0c;被索要500万元赎…

ISTQB选择国内版,还是国际版呢

1, ISTQB简介 ISTQB&#xff08;International Software Testing Qualifications Board&#xff09;是一个国际软件测试资格认证机构&#xff0c;旨在提供一个统一的软件测试认证标准。ISTQB成立于2002年&#xff0c;是非盈利性的组织&#xff0c;由世界各地的国家或地区软件测…

Logging 日志输出 - 无双重输出问题 - 可多个py文件 - Python

一、多个py文件每次只将一条日志输出到同一个log文件(yourpath\test)&#xff1a; &#xff08;一&#xff09;主文件&#xff1a; 1. logFile "yourpath\test" 2. if True: import logging from logging import handlers logger logging.getLogg…

Qt5 编译oracle数据库

库文件 1、Qt源码目录&#xff1a;D:\Qt5\5.15.2\Src\qtbase\src\plugins\sqldrivers\oci 2、oracle客户端SDK: https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html 下载各版本中的如下压缩包&#xff0c;一定要版本相同的 将两个压缩包…

事务,MySQL函数和索引详解

文章目录 事务简介提交方式手动提交事务 事务执行流程修改事务的默认提交方式 事务原理四大特性隔离级别 MySQL函数常见的日期函数判断函数case when字符串函数数字函数 MySQL性能(了解)索引概念分类MySQL索引语法数据结构(了解)BTreeBTree好处 优缺点优势劣势 创建原则 事务简…

c++取经之路(其五)——类和对象拷贝构造函数

概念&#xff1a;拷贝构造函数&#xff0c;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存在的类类型对象创建新对象时由编译器自动调用。 特征&#xff1a; 1. 拷贝构造函数是构造函数的一个重载形式 如&#xff1a; 2. 拷贝…