标准库bind函数

标准库bind函数

我们可以解决向check_size 传递一个长度参数的问题,方法是使用一个新的名为bind的标准库函数,它定义在头文件functional中。

可以将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为第二个参数,依此类推。

绑定check_size的sz参数

作为一个简单的例子,我们将使用bind生成一个调用check_size的对象,如下所示,它用一个定值作为其大小参数来调用check_size:

// check6是一个可调用对象,接受一个string类型的参数
//并用此string和值6来调用check_size
auto check6 = bind(check_size,_1,6);

此bind调用只有一个占位符,表示check6只接受单一参数。

占位符出现在arg_list的第一个位置,表示 check6的此参数对应 check_size的第一个参数。此参数是一个const string&。

因此,调用check6必须传递给它一个string类型的参数,check6会将此参数传递给check_size。

string s = "hello";
bool bl = check6(s);// check6(s)会调用 check size(s,6)

使用bind,我们可以将原来基于lambda的find_if调用:

auto wc=find_if(words.begin(),words.end(),
                    [szl(const string &a)


替换为如下使用check_size的版本:

auto wc = find_if(words.begin(),words.end(),
                        bind(check _size,_1, sz));

此bind调用生成一个可调用对象,将check_size的第二个参数绑定到 sz 的值。

当find_if对words中的string调用这个对象时,这些对象会调用check_size,将给定的string 和sz传递给它。因此,find_if可以有效地对输入序列中每个string调用check_size,实现string的大小与sz的比较。

使用placeholders名字

名字_n都定义在一个名为placeholders的命名空间中,而这个命名空间本身定义在std命名空间中。为了使用这些名字,两个命名空间都要写

与我们的其他例子类似,对bind的调用代码假定之前已经恰当地使用了using声明

例如,_1对应的using声明为:

using std::placeholders::_1;

此声明说明我们要使用的名字_1定义在命名空间placeholders中,而此命名空间又定义在命名空间std中。

对每个占位符名字,我们都必须提供一个单独的using 声明。编写这样的声明很烦也很容易出错。可以使用另外一种不同形式的using 语句,而不是分别声明每个占位符,如下所示:

using namespace namespace _name;

这种形式说明希望所有来自 namespace _name的名字都可以在我们的程序中直接使用。例
如:

using namespace std::placeholders;

使得由placeholders定义的所有名字都可用。与bind函数一样,placeholders命名空间也定义在functional头文件中。

bind的参数

如前文所述,我们可以用bind修正参数的值。更一般的,可以用bind绑定给定可调用对象中的参数或重新安排其顺序。例如,假定是一个可调用对象,它有5个参数,则下面对bind的调用:

//g是一个有两个参数的可调用对象
auto g= bind(f, a, b, _2, C,_1);

生成一个新的可调用对象,它有两个参数,分别用占位符_2和_1表示。

这个新的可调用对象将它自己的参数作为第三个和第五个参数传递给f。f的第一个、第二个和第四个参数分别被绑定到给定的值a、b和c上。

传递给g的参数按位置绑定到占位符。即,第一个参数绑定到_1,第二个参数绑定到2。因此,当我们调用g时,其第一个参数将被传递给f作为最后一个参数,第二个参数将被传递给f作为第三个参数。实际上,这个bind调用会将

g(_1,_2);

映射为

f(a, b,2, c,_1);

即,对g的调用会调用f,用g的参数代替占位符,再加上绑定的参数a、b和c。

例如,

调用

g(X,Y);

会调用

f(a, b, Y, c, X);

用bind重排参数顺序

下面是用bind重排参数顺序的一个具体例子,我们可以用bind颠倒isShroter的含义:

// 按单词长度由短至长排序
sort(words.begin(),words.end(),isShorter);

// 按单词长度由长至短排序
sort(words.begin(), words.end(), bind(isShorter,_2,_1));

在第一个调用中,当sort需要比较两个元素A和B时,它会调用isShorter(A,B)。

在第二个对sort的调用中,传递给isShorter的参数被交换过来了。

因此,当sort比较两个元素时,就好像调用isShorter(B,A)一样。

绑定引用参数

默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中。

但是,与lambda 类似,有时对有些绑定的参数我们希望以引用方式传递,或是要绑定参数的类型无法拷贝。
例如,为了替换一个引用方式捕获ostream 的 lambda:

//os是一个局部变量,引用一个输出流
// c是一个局部变量,类型为char
for each(words.begin(), words.end(),
            [&os, c](const string &s) { os << s<< c; });

可以很容易地编写一个函数,完成相同的工作:

ostream &print(ostream &os, const string &s, char c)
{
return os << s << c;
}

但是,不能直接用bind来代替对os的捕获:

//错误:不能拷贝0s
for_each(words.begin(), words.end(), bind(print, os,_1,' '));

原因在于bind拷贝其参数,而我们不能拷贝一个ostream。如果我们希望传递给bind一个对象而又不拷贝它,就必须使用标准库ref函数:

for_each(words.begin(), words.end(),
            bind(print, ref(os),_1,''));


函数ref返回一个对象,包含给定的引用,此对象是可以拷贝的。标准库中还有一个 cref函数,生成一个保存const 引用的类。与bind一样,函数ref和cref也定义在头文件 functional中。

向后兼容:参数绑定
旧版本 C++提供的绑定函数参数的语言特性限制更多,也更复杂。

标准库定义了两个分别名为bind1st和bind2nd的函数。

类似bind,这两个函数接受一个函数作为参数,生成一个新的可调用对象,该对象调用给定函数,并将绑定的参数传递给它。

但是,这些函数分别只能绑定第一个或第二个参数。由于这些函数局限太强,在新标准中已被弃用(deprecated)。所谓被弃用的特性就是在新版本中不再支持的特性。

新的C++程序应该使用bind。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Spring Boot的医疗服务系统设计与实现

基于Spring Boot的医疗服务系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 医疗服务系统首页界面图&#xff0c;公告信息、医疗地图…

快速幂笔记

快速幂即为快速求出一个数的幂&#xff0c;这样可以避免TLE&#xff08;超时&#xff09;的错误。 传送门&#xff1a;快速幂模板 前置知识&#xff1a; 1) 又 2) 代码&#xff1a; #include <bits/stdc.h> using namespace std; int quickPower(int a, int b) {int…

容斥原理以及Nim基础(异或,SG函数)

容斥原理&#xff1a; 容斥的复杂度为O&#xff08;2^m)&#xff0c;所以可以通过&#xff0c;对于实现&#xff0c;一共2^n-1种&#xff0c;我们可以用二进制来实现 下面是AC代码&#xff1a; #include<bits/stdc.h> using namespace std; typedef long long LL; cons…

uniapp 文字转语音(文字播报、语音合成)、震动提示插件 Ba-TTS

简介&#xff08;下载地址&#xff09; Ba-TTS 是一款uniapp语音合成&#xff08;tts&#xff09;插件&#xff0c;支持文本转语音&#xff08;无服务费&#xff09;&#xff0c;支持震动提示。 支持语音合成&#xff0c;文本转语音支持震动&#xff08;可自定义任意震动效果…

【云原生】Docker 实践(四):使用 Dockerfile 文件的综合案例

【Docker 实践】系列共包含以下几篇文章&#xff1a; Docker 实践&#xff08;一&#xff09;&#xff1a;在 Docker 中部署第一个应用Docker 实践&#xff08;二&#xff09;&#xff1a;什么是 Docker 的镜像Docker 实践&#xff08;三&#xff09;&#xff1a;使用 Dockerf…

【LinuxC语言】信号的基本概念与基本使用

文章目录 前言一、信号的概念二、信号的使用2.1 基本的信号类型2.2 signal函数 总结 前言 在Linux环境下&#xff0c;信号是一种用于通知进程发生了某种事件的机制。这些事件可能是由操作系统、其他进程或进程本身触发的。对于C语言编程者来说&#xff0c;理解信号的基本概念和…

36.Docker-Dockerfile自定义镜像

镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 镜像是分层机构&#xff0c;每一层都是一个layer BaseImage层&#xff1a;包含基本的系统函数库、环境变量、文件系统 EntryPoint:入口&#xff0c;是镜像中应用启动的命令 其他&#xff1a;在…

从0开始学习制作一个微信小程序 学习部分(6)组件与事件绑定

系列文章目录 学习篇第一篇我们讲了编译器下载&#xff0c;项目、环境建立、文件说明与简单操作&#xff1a;第一篇链接 第二、三篇分析了几个重要的配置json文件&#xff0c;是用于对小程序进行的切换页面、改变图标、控制是否能被搜索到等的操作第二篇链接、第三篇链接 第四…

QT的TcpServer

Server服务器端 QT版本5.6.1 界面设计 工程文件&#xff1a; 添加 network 模块 头文件引入TcpServer类和TcpSocket&#xff1a;QTcpServer和QTcpSocket #include <QTcpServer> #include <QTcpSocket>创建server对象并实例化&#xff1a; /*h文件中*/QTcpServer…

基于SSM SpringBoot vue宾馆网上预订综合业务服务系统

基于SSM SpringBoot vue宾馆网上预订综合业务服务系统 系统功能 首页 图片轮播 宾馆信息 饮食美食 休闲娱乐 新闻资讯 论坛 留言板 登录注册 个人中心 后台管理 登录注册 个人中心 用户管理 客房登记管理 客房调整管理 休闲娱乐管理 类型信息管理 论坛管理 系统管理 新闻资讯…

Docker-Compose编排LNMP并部署WordPress

前言 随着云计算和容器化技术的快速发展&#xff0c;使用 Docker Compose 编排 LNMP 环境已经成为快速部署 Web 应用程序的一种流行方式。LNMP 环境由 Linux、Nginx、MySQL 和 PHP 组成&#xff0c;为运行 Web 应用提供了稳定的基础。本文将介绍如何通过 Docker Compose 编排 …

BUUCTF---misc---被偷走的文件

1、题目描述 2、下载附件&#xff0c;是一个流量包&#xff0c;拿去wireshark分析&#xff0c;依次点开流量&#xff0c;发现有个流量的内容显示flag.rar 3、接着在kali中分离出压缩包&#xff0c;使用下面命令&#xff0c;将压缩包&#xff0c;分离出放在out3文件夹中 4、在文…

Java -- (part21)

一.File类 1.概述 表示文件或者文件夹的路径抽象表示形式 2.静态成员 static String pathSeparator:路径分隔符:; static String separator:名称分隔符:\ 3.构造方法 File(String parent,String child) File(File parent,String child) Flie(String path) 4.方法 获…

在M1芯片安装鸿蒙闪退解决方法

在M1芯片安装鸿蒙闪退解决方法 前言下载鸿蒙系统安装完成后&#xff0c;在M1 Macos14上打开闪退解决办法接下来就是按照提示一步一步安装。 前言 重新安装macos系统后&#xff0c;再次下载鸿蒙开发软件&#xff0c;竟然发现打不开。 下载鸿蒙系统 下载地址&#xff1a;http…

Android使用kts上传aar到JitPack仓库

Android使用kts上传aar到JitPack 之前做过sdk开发&#xff0c;需要将仓库上传到maven、JitPack或JCenter,但是JCenter已停止维护&#xff0c;本文是讲解上传到JitPack的方式,使用KTS语法&#xff0c;记录使用过程中遇到的一些坑. 1.创建项目(library方式) 由于之前用鸿神的w…

每日OJ题_贪心算法二⑥_力扣409. 最长回文串

目录 力扣409. 最长回文串 解析代码 力扣409. 最长回文串 409. 最长回文串 难度 简单 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个…

【Java从入门到精通】Java继承

继承的概念 继承是java面向对象编程技术的一块基石&#xff0c;因为它允许创建分等级层次的类。 继承就是子类继承父类的特征和行为&#xff0c;使得子类对象&#xff08;实例&#xff09;具有父类的实例域和方法&#xff0c;或子类从父类继承方法&#xff0c;使得子类具有父…

Linux 麒麟系统安装

国产麒麟系统官网地址&#xff1a; https://www.openkylin.top/downloads/ 下载该镜像后&#xff0c;使用VMware部署一个虚拟机&#xff1a; 完成虚拟机创建。点击&#xff1a;“开启此虚拟机” 选择“试用试用开放麒麟而不安装&#xff08;T&#xff09;”&#xff0c;进入op…

React Native支持Tailwind CSS 语法

React Native支持Tailwind CSS 语法 一、前沿背景 回想下我们平时按照官方的规范进行书写样式是什么样&#xff1f; 是像下面这样&#xff1a; const MyComponent () > {return (<View><Text style{{ fontSize: 20 }}>开发者演示专用</Text></View…

【论文阅读】Tutorial on Diffusion Models for Imaging and Vision

1.The Basics: Variational Auto-Encoder 1.1 VAE Setting 自动编码器有一个输入变量x和一个潜在变量z Example. 获得图像的潜在表现并不是一件陌生的事情。回到jpeg压缩&#xff0c;使用离散余弦变换&#xff08;dct&#xff09;基φn对图像的底层图像/块进行编码。如果你给…
最新文章