C++11函数适配器bind() --- C++11新语法bind() 你了解多少?什么是适配器???

news2024/11/8 2:50:23

文章目录

  • 1.介绍
    • 头文件
    • 定义
    • 原型
  • 2.引入
    • 2.1现有语法无法解决
    • 2.2bind的文档阅读
    • 2.3bind()绑定函数对于2.1问题的解决

1.介绍

头文件

#include <functional> 

定义

bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接收一个可调用对象(callable object),生成一个新的可调用对象来==“适应”原对象的参数列表==。用它可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个(M可以大于N,但这么做没什么意义)参数的新函数。同时,使用bind函数还可以实现参数顺序调整等操作。

简而言之

bind函数用于把已知函数与某种参数与进行绑定,形成新的函数。

什么叫做绑定?

更改已知函数调用模式

如何理解bind?

可以将bind函数看作是一个通用的函数适配器,接收一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。调用bind的一般形式:auto newCallable = bind(callable,arg_list);
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示
newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对
象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推。

原型

template <class Fun, class... Args>
bind (Fun&& fun, Args&&... args);

template <class Ret, class Fun, class... Args>
bind (Fun&& fun, Args&&... args);

2.引入

2.1现有语法无法解决

int Myplus(int a, int b)
{
	return a + b;
}

class Sub
{
public:
	int Mysub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	function<int(int, int)> funcPlus = Myplus;
	function<int(Sub, int, int)> funcSub = &Sub::Mysub;
	map<string, function<int(int, int)>> m =
	{
		{ "+", Myplus},
		{ "-", &Sub::Mysub}
	};
}

即 一个全局函数 一个类 现在我们想要把这两个函数通过包装器包装起来 我们的目的无法达到 因为两个函数传给包装器时 方式不同 包装时无法统一 怎么解决?

class Mycalculator
{
public:
	int Myplus(int a, int b)
	{
		return a + b;
	}
	int Mysub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	function<int(Mycalculator,int, int)> funcPlus = &Mycalculator::Myplus;
	function<int(Mycalculator, int, int)> funcSub = &Mycalculator::Mysub;
	map<string, function<int(Mycalculator, int, int)>> m =
	{
		{ "+", &Mycalculator::Myplus},
		{ "-", &Mycalculator::Mysub}
	};
}

很明显 上面强制他们统一 同样的也可以把类转成全局函数 但这都不是我们想要的结果 怎么办呢???

此时 bind绑定就出来了…

2.2bind的文档阅读

在这里插入图片描述
返回一个基于fn的函数对象,但其参数绑定为args。
每个实参可以绑定到一个值或一个占位符:
-如果绑定到一个值,调用返回的函数对象将始终使用该值作为参数。
-如果是占位符,调用返回的函数对象会将一个参数传递给调用(其顺序号由占位符指定)。
调用返回的对象返回与fn相同的类型,除非指定了特定的返回类型为Ret(2)(注意,Ret是唯一不能通过传递给此函数的实参隐式推断的模板形参)。
返回对象的类型具有以下属性:
它的函数调用返回与fn相同的参数绑定到args…(或转发,用于占位符)。
对于(1),它可以有一个成员result_type:如果Fn是指向函数或成员函数类型的指针,它被定义为其返回类型的别名。否则,如果存在这样的成员类型,则定义为Fn::result_type。
对于(2),它有一个成员result_type,定义为Ret的别名。
它是可移动构造的,如果它的所有参数的类型都是可复制构造的,那么它也是可复制构造的。两个构造函数都不会抛出,只要没有相应的Fn和Args衰变类型的构造函数…扔。
在这里插入图片描述fn
函数对象,指向函数的指针或指向成员的指针。
Fn应具有可从Fn移动构造的衰变类型。
args……
要绑定的参数列表:值或占位符。
Args中的类型…应具有可从args…中各自的参数移动构造的衰变类型
如果对于任何参数,其衰减类型是reference_wrapper,则将其绑定到其引用的值。

在这里插入图片描述
一个函数对象,被调用时调用fn,其参数绑定到args。

如果fn是指向成员的指针,则返回函数期望的第一个参数是类的对象*fn是成员(或对其的引用,或指向其的指针)。
在这里插入图片描述
在这里插入图片描述

namespace placeholders
{  
    extern /* unspecified */ _1; 
    extern /* unspecified */ _2; 
    extern /* unspecified */ _3;  
    // ...
}

在这里插入图片描述
在这里插入图片描述

2.3bind()绑定函数对于2.1问题的解决

int pLus(int a, int b)
{
	return a + b;
}

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};

int Mul(int a, int b, int c)
{
	return a * b * c;
}

int Div(int a, int b)
{
	return a / b;
}
using namespace placeholders;
int main()
{
	function<int(int, int)> funcPlus = pLus;

	//function<int(Sub, int, int)> funcSub = &Sub::sub;
	function<int(int, int)> funcSub = bind(&Sub::sub, Sub(), _1, _2);

	function<int(int, int, int)> funcMul = bind(Mul, _1, _2, _3);
	
	map<string, function<int(int, int)>> m =
	{
		{ "+", pLus},
		{ "-", bind(&Sub::sub, Sub(), _1, _2)}
	};

	cout << "funcPlus(1, 2) == " << funcPlus(1, 2) << endl << endl;
	
	cout << "bind(&Sub::sub, Sub(), _1, _2) == " << funcSub(1, 2) << endl << endl;
	cout << "bind(Mul, _1, _2, _3) == " << funcMul(1, 2, 3) << endl << endl;
	auto funcMul2 = bind(Mul, 1, 2, 3);
	cout << "funcMul2() == " << funcMul2() << endl << endl;
	cout << "m["" + ""](1, 2) == " << m["+"](1, 2) << endl << endl;
	cout << "m["" - ""](1, 2) == " << m["-"](1, 2) << endl << endl;

	return 0;
}

在这里插入图片描述

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

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

相关文章

苹果 AirPods Pro 2 耳机新固件(6A305)

苹果公司对采用 Lightning 端口和 USB-C 端口的 AirPods Pro 2 耳机&#xff0c;推出了内部编号为 6A305 的全新固件&#xff0c;高于 10 月 10 日发布的 6A303 更新。用户无需手动更新&#xff0c;只需将 AirPods 通过蓝牙连接到 iPhone &#xff0c;此时便会自动安装新的固件…

甄知科技张礼军:数智化转型助企业破茧成蝶!

数智化浪潮滚滚向前&#xff0c;正席卷各行各业&#xff0c;带领企业从数字化时代跨入数智化时代。可什么是数智化&#xff1f;如何实现数智化转型&#xff1f;已经成为横亘在无数企业面前的大难题&#xff01; 事实上&#xff0c;数智化是数字化、AI和业务三个要素的交集&…

SQLServe联合主键、联合索引、唯一索引,聚集索引,和非聚集索引、主键、唯一约束和外键约束、索引运算总结

联合主键 SQL server 中给表增加联合主键的两种方法 第一种方法&#xff0c;新建表时增加联合主键&#xff1a; create table t_students(id int not null,name varchar(10) not null Primary Key (id, name),age int,dept_id int )注&#xff1a;联合主键的列需要限制非空约…

操作系统【OS】系统调用

系统调用 定义 操作系统对应用程序和程序员提供的接口用户程序执行陷入指令&#xff08;Trap或访管指令&#xff09;来发起系统调用&#xff0c;请求操作系统提供服务OS 通过提供系统调用避免用户程序直接访问外设【应用程序通过系统调用使用OS的设备管理服务】操作系统不同, …

弹出框,使用树结构查询数据

效果如下: 描述:希望点击某个按钮,弹出一个窗口,然后通过下拉框,点击下拉框里面的组织信息,然后查询对应组织的成员对象列表,并展示到表格中 HTML代码(最主要的就是树的那个): <el-dialog :visible.sync="TesteePage.showDialog" width="70%&quo…

初出茅庐的小李博客之Windows11运行Linux记录

安装教程 超简单&#xff0c;不安装虚拟机&#xff0c;Windows11运行Linuxhttps://zhuanlan.zhihu.com/p/393484912 注意事项 出现错误有可能是少了驱动 驱动下载地址 https://link.zhihu.com/?targethttps%3A//wslstorestorage.blob.core.windows.net/wslblob/wsl_updat…

bp(back propagation)

文章目录 定义过程前向传播计算过程计算损失函数&#xff08;采用均方误差MSE&#xff09;反向传播误差&#xff08;链式法则&#xff09;计算梯度更新参数 简单实例 定义 反向传播全名是反向传播误差算法&#xff08;Backpropagation&#xff09;&#xff0c;是一种监督学习方…

HZOJ-271: 滑动窗口

题目描述 ​ 给出一个长度为 N&#xfffd; 的数组&#xff0c;一个长为 K&#xfffd; 的滑动窗口从最左移动到最右&#xff0c;每次窗口移动&#xff0c;如下图&#xff1a; 找出窗口在各个位置时的极大值和极小值。 输入 ​ 第一行两个数 N,K&#xfffd;,&#xfffd;。 …

win yolov5.7 tensorRT推理

安装TensorRT 下载tensorrt8.xx版本&#xff0c;适用于Windows的cuda11.x的版本 官方下载地址https://developer.nvidia.com/nvidia-tensorrt-8x-download 把tensorRT里面的bin、include、lib添加到本机CUDA中&#xff0c;CUDA需要加入环境变量中 配置虚拟环境 torch的版本…

Confluence最新版本(8.6)安装

软件获取 Confluence 历史版本下载地址&#xff1a;Confluence Server 下载存档 | Atlassian Atlassian-agent.jar https://github.com/haxqer/confluence/releases/download/v1.3.3/atlassian-agent.jar MySQL 驱动包 MySQL :: Download MySQL Connector/J (Archived Ve…

举个栗子!Alteryx 技巧(6):从 API 中提取数据

你听说过从 API 中提取数据吗&#xff1f;API 是指应用编程接口&#xff0c;是计算机之间或计算机程序之间的连接&#xff0c;它是一种软件接口&#xff0c;让不同的软件进行信息共享。对于很多数据分析师来说&#xff0c;他们常常需要从 API 中提取数据&#xff0c;那么如何快…

ASEMI肖特基二极管MBR10200CT在电子电路中起什么作用

编辑-Z 肖特基二极管MBR10200CT是一种特殊类型的二极管&#xff0c;可以在电子电路中起到多种作用。 首先&#xff0c;MBR10200CT具有非常低的正向电压丢失和快速的开关速度。这使得它非常适合用作整流器。在直流电源中&#xff0c;MBR10200CT可以将交流电转换为直流电&#x…

漏洞复现--蓝凌EIS智慧协同平台任意文件上传

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

【LCR 159. 库存管理 III】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:int getrandom(int left,int right,vector<int>& stock){return stock[rand()%(right-left1)left];}void qsort(int l,int r,vector<int>& s…

【uni-app+vue3】分享功能,App端调用手机的系统分享,可分享到微信、QQ、朋友圈等,已实现

前言&#xff1a; uniapp分享功能&#xff0c;之前考虑的思路一直都是如何使用uni.share()实现 需要下载插件&#xff0c;需要申请微信appid&#xff0c;插件已下载&#xff0c;主要就是没有appid&#xff0c;所以只好换方向 实现效果&#xff1a; 在需要分享的页面&#xff0c…

嵌入式学习笔记(59)内存管理之栈

1.6.1.什么是栈&#xff08;Stack&#xff09; 栈是一种数据结构&#xff0c;C语言中使用栈来存放局部变量。 1.6.2.栈管理内存的特点&#xff08;小内存、自动化&#xff09; 先进后出 FILO&#xff08;First In Last Out&#xff09; 栈 先进先出 FIFO&#xff08;First …

聚类方法总结及code

参考链接 聚类方法的分类&#xff1a; 类别包括的主要算法划分方法K-Means算法&#xff08;均值&#xff09;、K-medoids算法&#xff08;中心点&#xff09;、K-modes算法&#xff08;众数&#xff09;、k-prototypes算法、CLARANS&#xff08;基于选择&#xff09;&#xf…

jmeter接口测试避坑指南

接口测试看着很简单&#xff0c;但是操作过程中还是出现很多问题&#xff0c;现总结如下&#xff1a; 一、jmeter中乱码问题 可在jmeter.properties 这个文件里面找到sampleresult.default.encodingxx&#xff0c;后面xx改成utf-8&#xff0c;然后取消注释。 解决jmeter的bod…

编译和连接

前言&#xff1a;哈喽小伙伴们&#xff0c;从我们开始学习C语言到实现如今的成果&#xff0c;可以说我们对C语言的掌握已经算是精通级别了&#xff0c;但是我们只学习了怎么写代码&#xff0c;却没怎么了解过代码的背后是怎么工作的。 那么今天这篇文章我们一起来学习C语言的最…

spark获取hadoop服务token

spark 作业一直卡在accepted 问题现象问题排查1.查看yarn app日志2.问题分析与原因 问题现象 通过yarn-cluster模式提交spark作业&#xff0c;客户端日志一直卡在submit app&#xff0c;没有运行 问题排查 1.查看yarn app日志 appid已生成&#xff0c;通过yarn查看app状态为…