C++11——function与bind

news2024/11/23 21:29:04

包装器

  • function包装器
    • function的介绍
    • function的使用
    • function的使用场景
    • function的意义
  • bind包装器
    • bind的介绍
    • bind的使用

function包装器

function的介绍

function是用来包装函数的,所以叫做包装器或者适配器,fuction的本质其实是一个类模板
function的类模板如下:

template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;

参数说明:

  • Ret:被包装的可调用对象的返回值类型。
  • Args…:被包装的可调用对象的形参类型。

function的使用

在使用function的时候,需要包含头文件#include< functional >
function可以对一下五种函数进行包装:

  • 函数指针
int add(int a, int b)
{
	return a + b;
}
int main()
{
	std::function<int(int, int)> func1 = add;//传递函数指针
	std::cout << func1(1, 1) << std::endl;
	return 0;
}
  • 仿函数(函数对象)
struct plus
{
	int operator()(int a,int b)
	{
		return a + b;
	}
};
int main()
{
	std::function<int(int, int)> func2 = plus();//传递仿函数(函数对象)
	std::cout << func2(3, 4) << std::endl;
	return 0;
}

需要注意的是,传递的是一个函数对象,因为仿函数operator()是创建在对象中的

  • lambda表达式
int main()
{
	std::function<int(int, int)> func3 = [](int a, int b)->int {return a + b; };
	//传递lambda函数
	std::cout << func3(5, 6) << std::endl;
	return 0;
}
  • 静态成员函数
class Func
{
public:
	static int addi(int a,int b)
	{
		return a + b;
	}

	double addd(double a,double b)
	{
		return a  + b;
	}
};
int main()
{
	std::function<int(int, int)> func4 = &Func::addi;//传递静态类成员函数,可以省略&
	std::cout << func4(5, 6) << std::endl;
	return 0;
}
  • 传递非静态成员函数
class Func
{
public:
	static int addi(int a,int b)
	{
		return a + b;
	}

	double addd(double a,double b)
	{
		return a  + b;
	}
};
int main()
{
	std::function<int(Func,double, double)> func5 = &Func::addd;//传递非静态成员函数,不可以省略&
	std::cout << func5(Func(), 5.5, 6.6) << std::endl;
	return 0;
}

需要注意的,在传递非静态成员函数的时候,&是不可以省略的,而且还要多传递一个成员变量this指针,所以可以就传递一个临时变量Func()。

function的使用场景

统一类型的使用场景:
函数模板会根据不同的模板参数,实例化出等同于不同模板参数函数的实例,假设有一个函数模板:
第一个模板参数是可以任意调用的函数指针,仿函数,lambda表达式;
第二个模板参数是任意的自定义类型或内置类型。

template<class T,class F>
T useF(F f,T a)
{
	static int num = 0;
	cout << "num的值: " << ++num << endl;
	cout << "num的地址: " << &num << endl;
	return f(a);
}
int add(int a)
{
	return 1 + a;
}
struct Func 
{
	int operator()(int a)
	{
		return 1 + a;
	}
};
int main()
{
	cout << useF(add,1) << endl;
	cout << useF(Func(),1) << endl;
	cout << useF([](int a)->int {return 1 + a; }, 1) << endl;
	return 0;
}

在这里插入图片描述
这样实例化出来了三份不同的函数实例,造成这样的现象是因为第一个模板参数。
现在有解决方法就是吧,函数指针和仿函数以及lambda全部都用function包装起来,然后再传给useF那么就只会实例化出来一份函数实例。
在这里插入图片描述

function的意义

  • 将可调用对象的类型进行统一,便于对其进行统一化管理。
  • 包装后明确了可调用对象的返回值和形参类型,更加方便使用者使用。

bind包装器

bind的介绍

bind也是可以包装函数的一种方法,bind可以包装一个可调用的对象(函数),然后生成一个新的可调用对象(函数)去适配原来这个可调用对象(函数)的参数bind的本质是一个函数模板

template <class Fn, class... Args>
/* unspecified */ bind(Fn&& fn, Args&&... args);
template <class Ret, class Fn, class... Args>
/* unspecified */ bind(Fn&& fn, Args&&... args);

参数说明:

  • Fn:可调用的对象
  • Args:参数列表,占位符

bind的使用

调用bind的一般形式为:auto newCallable = bind(callable, arg_list);

  • callable:需要包装的可调用对象。
  • newCallable:生成的新的可调用对象。
  • arg_list:逗号分隔的参数列表,对应给定的callable的参数。当调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
int sub(int a, int b)
{
	return a - b;
}
int main()
{
	auto newsub = bind(sub,placeholders::_1,placeholders::_2);
	cout << newsub(2,1) << endl;
}

auto可以用function来代替,function<()()> newCallable = bind(callable, arg_list);

int sub(int a, int b)
{
	return a - b;
}
int main()
{
	function<int(int, int)> newsub = bind(sub, placeholders::_1, placeholders::_2);
	cout << newsub(2, 1) << endl;
}

其中的placeholsers::_1和placeholders::_2,对应的就是sub的第一个参数和第二个参数。
bind传递参数的顺序
在这里插入图片描述
placeholders_n,是按照顺序绑定可调用对象的参数的是不会改变的。
bind包装类成员函数:

class func
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	function<int(int, int)> newsub = bind(&func::sub,func(),placeholders::_1,placeholders::_2);
	cout << newsub(2,1)  << endl;
	return 0;
}

需要注意:类成员函数的又this指针,所以需要在传递可调用对象这个参数之后,再传递一个临时变量给this指针。

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

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

相关文章

Mac使用gradle编译springboot-2.7.x源码

1 开发环境&#xff1a; JDK8 ideaIU-2024.2.2 gradle-7.6.3 代理网络 2 下载springboot源码 代码仓库网址 git clone -b 2.7.x https://github.com/spring-projects/spring-boot.git3 安装gradle gradle下载网址 https://services.gradle.org/distributions/ 安装此文件指…

Three.js 3D人物漫游项目(上)

本文目录 前言1、项目构建1.1 安装依赖1.2 初始化1.3 项目结构1.4 初始化的项目运行 2、加载模型2.1 threejs三要素2.1.1 代码解读 2.2 加载模型2.2.1 代码解读 2.3 效果 前言 在数字技术的浪潮中&#xff0c;三维图形渲染技术以其独特的魅力&#xff0c;正逐步渗透到我们生活的…

基于无人机影像的可见光单木分割数据集-json格式

基于无人机影像的可见光单木分割数据集&#xff0c;共1700张影像&#xff0c;数据集大小3.6GB&#xff0c;分割标注采用标准json格式。 该数据集是一个专门用于基于无人机可见光影像进行单木分割的数据集&#xff0c;旨在帮助研究人员和开发者训练和评估基于深度学习的图像分割…

4.5 pandas 实战 分析抖音播放数据(1)

课程目标 基于pandas对抖音播放数据做数据分析 数据准备 点此去下载 课程内容 导包 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns plt.rcParams["font.family"] "SimHei" plt.rcParams["ax…

道路坑洞分割数据集/道路裂纹分割数据集

1.道路坑洞,道路裂纹分割数据集&#xff0c;包含5790张坑洞分割图像数据&#xff08;默认分割标注png图片&#xff0c;850MB&#xff09;2.10000余张道路裂纹图像数据&#xff08;默认分割标注png图片&#xff0c;3.7GB&#xff09;3。道路坑洞&#xff0c;道路 道路坑洞与裂纹…

关于“华为杯”第二十一届中国研究生数学建模竞赛赛题下载及提交作品的重要提醒

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 各参赛队伍&#xff1a; “华为杯”第二十一届中国研究生数学建模竞赛即将于2024年…

零基础玩转实在Agent -- 基础篇|实在Agent研究

前言 实在Agent是什么 实在Agent&#xff08;智能体&#xff09;是实在智能基于RPA和自研屏幕语义理解技术&#xff0c;结合最前沿的Al大模型打造的自动化智能体产品。 它能像朋友一样聊天&#xff0c;并通过对话的方式理解你的任务需求&#xff0c;自动规划任务的实现方式&…

Qt clicked()、clicked(bool)、toggled(bool)信号的区别和联系

clicked() 信号 所属控件&#xff1a;clicked()信号是QAbstractButton类&#xff08;及其子类&#xff0c;如QPushButton、QRadioButton、QCheckBox等&#xff09;的一个信号。clicked信号可以说是许多控件&#xff08;特别是按钮类控件&#xff0c;如QPushButton&#xff09;…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0920)

十三、文章分类页面 - [element-plus 表格] Git仓库&#xff1a;https://gitee.com/msyycn/vue3-hei-ma.git 基本架子 - PageContainer 功能需求说明&#xff1a; 基本架子-PageContainer封装文章分类渲染 & loading处理文章分类添加编辑[element-plus弹层]文章分类删除…

Vue3DevTools7是如何在vscode定位指定文件位置的?

Vue3DevTools7是如何在vscode定位指定文件位置的&#xff1f; 背景 今天在使用vue脚手架创建项目的时候&#xff0c;并发现一个新的&#xff08;实验中的新功能&#xff09;&#xff0c;可以直接在我们的项目中集成Vue DevTools插件&#xff0c;浏览器插件devtools即将成为历史…

第十三周:机器学习笔记

第十三周周报 摘要Abstract一、机器学习——Transformer&#xff08;上&#xff09;1. Sequence to Sequence(Seq 2 Seq&#xff0c;序列到序列模型) 的应用2. Transformer的结构2.1 Transformer encoder&#xff08;Transformer 编码器&#xff09; 二、Pytorch学习1. 网络模型…

python爬虫初体验(一)

文章目录 1. 什么是爬虫&#xff1f;2. 为什么选择 Python&#xff1f;3. 爬虫小案例3.1 安装python3.2 安装依赖3.3 requests请求设置3.4 完整代码 4. 总结 1. 什么是爬虫&#xff1f; 爬虫&#xff08;Web Scraping&#xff09;是一种从网站自动提取数据的技术。简单来说&am…

BandiView 7.03 看图软件

BandiView 加入了大量现代化功能特性&#xff0c;比如支持 HDR 照片高动态范围效果、支持 HEIC / RAW / 漫画模式、免解压直接看图、查看 AI 图片提示词等 BandiView 是一款非常值得推荐的电脑全能看图浏览工具软件&#xff0c;软件的兼容性非常强&#xff0c;可以一站式满足用…

java通过org.eclipse.milo实现OPCUA客户端进行连接和订阅

前言 之前写过一篇关于MQTT的方式进行物理访问的文章&#xff1a;SpringBoot集成MQTT&#xff0c;WebSocket返回前端信息_springboot mqtt websocket-CSDN博客 最近又接触到OPCUA协议&#xff0c;想通过java试试看能不能实现。 软件 在使用java实现之前&#xff0c;想着有没…

欠款管理代码———未来之窗行业应用跨平台架构

一、欠款管理代码 function fun_会员_还款操作(会员卡信息id,MainID){var 未来之窗vos对话框_内容 ";var title"test";var 未来之窗vos对话框_id"hjksgfjkkhkj_child";CyberWin_Dialog.layer(未来之窗vos对话框_内容,{type:"url",title:&…

windows下,用docker部署xinference,为什么老是提示localhost无法访问?

部署xinference有两种方式&#xff1a; 一、本地部署 &#xff08;略&#xff09; 二、使用Docker部署&#xff08;与运行&#xff09; 其中又包括&#xff1a; 1&#xff09;使用CPU的方式&#xff1a;&#xff08;略&#xff09; 1&#xff09;使用GPU的方式&#xff1…

LeetCode_sql_day30(1264.页面推荐)

描述 1264.页面推荐 朋友关系列表&#xff1a; Friendship ------------------------ | Column Name | Type | ------------------------ | user1_id | int | | user2_id | int | ------------------------ (user1_id, user2_id) 是这张表具有唯一值的…

低代码可视化工具--vue条件判断v-if可视化设置-代码生成器

在Vue UniApp中&#xff0c;条件判断通常是通过指令v-if、v-else-if、v-else来实现的。这些机制允许你根据表达式的真假值来决定是否渲染某个元素或元素组&#xff0c;或者执行特定的逻辑。 条件判断说明 v-if 是惰性的&#xff1a;如果在初始渲染时条件为假&#xff0c;则什么…

mac os x 找不到钥匙串访问

昨天手贱更新了最新的mac系统&#xff0c;结果在实用工具中找不到钥匙串访问APP了。。。 最新mac系统为 15.0 (24A335) 真是醉了。。。 那就得想办法把他给呼出来&#xff0c;在开发者中心下载了一个.cer文件&#xff0c;然后双击打开&#xff0c;此时钥匙串打开了&#xff…