C++11|包装器

news2024/11/29 10:41:49

目录

引入 

一、function包装器

1.1包装器使用

1.2包装器解决类型复杂 

二、bind包装器


引入 

在我们学过的回调中,函数指针,仿函数,lambda都可以完成,但他们都有一个缺点,就是类型的推导复杂性,从而会导致某一问题,例如:

#include <iostream>
using namespace std;


// 定义一个仿函数
struct DivideByTwo {
    double operator()(double num) {
        return num / 2.0;
    }
};

// 定义一个函数
double divideByThree(double num) {
    return num / 3.0;
}


template <class F,class T>
T useF(F f, T x)
{
    return f(x);
}

int main() {


    // 直接使用仿函数
    cout << useF(DivideByTwo(), 10.0) << endl;

    // 直接使用函数指针
    cout << useF(divideByThree, 10.0) << endl;

    //lambda表达式
    cout << useF([](double d) {return d / 4; }, 10.0) << endl;

    return 0;
}

输出结果:

在上述示例中,由于类型的复杂,useF函数模板需要实例化三份,从而使得代码变得相对冗余,面对这种问题,function包装器可以带来一定的优化。那么接下来讲讲包装器的用法,然后来解决这个问题。

一、function包装器

1.1包装器使用

function包装器也叫适配器,是一个类模板。因为是一个适配器,所以可以适配出函数指针,仿函数,lambda的用法。

std::function包装器在头文件functional>

 类模板原型如下:

template <class Ret, class... Args>

class function<Ret(Args...)>;

模板参数说明: Ret: 被调用函数的返回类型

Args…:被调用函数的形参

#include <iostream>
using namespace std;
#include <functional>
int f(int a, int b)
{
	return a + b;
}
struct Functor
{
public:
	int operator() (int a, int b)
	{
		return a + b;
	}
};
class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}
	double plusd(double a, double b)
	{
		return a + b;
	}
};
int main()
{
	// 函数名(函数指针),
	function<int(int, int)> func1 = f;//将函数指针传给包装器,就可以适配出具有相应函数指针的功能
	cout << func1(1, 2) << endl;//调用的就是函数f,被调用函数的返回值类型是int,形参是int,int

	// 函数对象
	function<int(int, int)> func2 = Functor(); //将仿函数对象传给包装器,就可以适配出仿函数
	cout << func2(1, 2) << endl;//调用的就是仿函数operator(),被调用仿函数的返回值类型是int,形参是int,int

	// lambda表达式
	function<int(int,int)> func3 = []( int a, int b){return a + b; };//将lambda传给包装器,就可以适配出lambda
	cout << func3(1, 2) << endl;//调用的就是lambda,而其底层是仿函数,即调用对应的operator(),被调用仿函数的返回值类型是int,形参是int,int

	// 类的成员函数,注意:成员函数取地址必须加&,由于是在类外,所以还得加上类域
	function<int(int, int)> func4 = &Plus::plusi;//将静态成员函数指针传给包装器,就可以适配出具有相应成员函数指针的功能
	cout << func4(1, 2) << endl;//调用的就是plusi函数

	function<double(Plus*, double, double)> func5 = &Plus::plusd;//由于是非静态成员函数,其多了一个this指针,所以得多带上一个参数
	//cout << func5(&Plus(), 1.1, 2.2) << endl;//由于plus()是一个匿名对象,属于右值,右值不能够取地址,所以不能这样写
	Plus ps;//得额外定义一个对象
	cout << func5(&ps, 1.1, 2.2) << endl;

	//还可以这种写法,相当于用对象去调用了这个成员函数,可以认为是编译器的特殊处理
	function<double(Plus, double, double)> func6 = &Plus::plusd;
	cout << func6(Plus(), 1.1, 2.2) << endl;
	return 0;
}

输出结果:

1.2包装器解决类型复杂 

回到最开始引入的问题, 使用包装器就可以解决,如下:

int main() {


    // 直接使用仿函数
    function<double(double)> func1 = DivideByTwo();
    cout << useF(func1, 10.0) << endl;

    // 直接使用函数指针
    function<double(double)> func2 = divideByThree;
    cout << useF(func2, 10.0) << endl;

    //lambda表达式
    function<double(double)> func3 = [](double d) {return d / 4; };
    cout << useF(func3, 10.0) << endl;
   

    return 0;
}

 输出结果:

function<double(double)> 作为参数传递给 useF 函数模板。那么,模板会根据这个特定的参数类型(即接受一个 double 类型参数并返回 double 类型值的可调用对象)进行一次实例化。无论以这种类型的function 调用 useF 函数多少次,只要参数类型不变,都只会进行这一次实例化。相比较传入不同类型实例化有效地减少了实例化的次数和复杂性

二、bind包装器

也是定义在functional文件中,是一个函数模板,

原型如下:

template class Fn, class... Args>

bind (Fn&& fn, Args&&... args);

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

也是一个函数包装器(适配器),callabl代表可调用函数,arg_list用来接收绑定多个参数,以逗号分割,从而生成一个新的参数列表来替换原函数的参数列表,并将该bind函数对象赋值给newCallable,当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。

arg_list中的参数可能包含形如_n的名字(属于placeholders类域),其中n是一个整数,这些参数是“占位符”,表示 newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示newCallable中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推。概念还是抽象的,通过例子来演示:

#include <iostream>
using namespace std;
#include <functional>
int Plus(int a, int b)
{
	return a + b;
}
class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	//表示绑定函数plus 参数分别由调用 func1 的第一,二个参数指定,并用function包装器包装bind
	function<int(int, int)> func1 = bind(Plus, placeholders::_2, placeholders::_1);//绑定参数,_2代表func1的第二个参数在第一个位置,_1代表func2的第一个参数在第二个位置
	//相当于第一个参数替换成了2,第二个替换成了1,即1传给了b,2传给了a
	cout << func1(1, 2) << endl;//调用Plus函数

	//auto func1 = std::bind(Plus, placeholders::_1, placeholders::_2);
	

	//func2的类型为 function<void(int, int, int)> 与func1类型一样
	//表示绑定函数 plus 的第一,二为: 1, 2
	auto func2 = bind(Plus, 1, 2);//绑定参数,这些参数替换原来的参数,即func2的参数替换成了1,2
	cout << func2(2,3) << endl;//调用Plus函数


	// 绑定成员函数
	std::function<int(int, int)> func3 = std::bind(&Sub::sub, Sub(), placeholders::_1, placeholders::_2);
	cout << func3(1, 2) << endl;


	std::function<int(int, int)> func4 = std::bind(&Sub::sub, Sub(), placeholders::_2, placeholders::_1);
	cout << func4(1, 2) << endl;
	return 0;
}

输出结果:

总结一句话,bind通过更改原函数参数列表来包装新函数。 

end~ 

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

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

相关文章

【TORCH】绘制权重分布直方图,权重torch.fmod对torch.normal生成的随机数进行取模运算

要绘制上述代码中权重初始化的分布&#xff0c;可以分别展示每一层初始化权重的直方图。我们将用 torch.fmod 对 torch.normal 生成的随机数进行取模运算&#xff0c;确保权重值在 -2 到 2 之间。 含义解释 torch.normal(0, init_sd, size...)&#xff1a;生成服从均值为 0、…

编译Open Cascade(OCC)并使用C#进行开发

说明&#xff1a; VS版本&#xff1a;Visual Studio Community 2022系统&#xff1a;Windows 11 专业版23H2Open CASCADE&#xff1a;v7.7.0&#xff08;链接&#xff1a;https://pan.baidu.com/s/1-o1s4z3cjpYf5XkwhSDspQ?pwdp9i5提取码&#xff1a;p9i5&#xff09; 下载和…

【Kafka】Kafka生产者开启幂等性后报错:Cluster authorization failed.

文章目录 背景解决服务端配置ACL增加授权 背景 用户业务需求&#xff0c;需要开启生产者的幂等性&#xff0c;生产者加了配置&#xff1a;enable.idempotence true用户使用的集群开启了ACL认证&#xff1a;SASL_PLAINTEXT/SCRAM-SHA-512用户生产消息时报错&#xff1a;org.ap…

[笔记] 卷积 - 02 滤波器在时域的等效形式

1.讨论 这里主要对时域和频域的卷积运算的特征做了讨论&#xff0c;特别是狄拉克函数的物理意义。 关于狄拉克函数&#xff0c;参考这个帖子&#xff1a;https://zhuanlan.zhihu.com/p/345809392 1.狄拉克函数提到的好函数的基本特征是能够快速衰减&#xff0c;对吧&#xf…

VBA提取word表格内容到excel

这是一段提取word表格中部分内容的vb代码。 Sub 提取word表格() mypath ThisWorkbook.Path & "\"myname Dir(mypath & "*.doc*")n 4 index of rowsRange("A1:F1") Array("课程代码", "课程名称", "专业&…

云服务器在 Web 应用程序中作用

云服务器在Web应用程序中扮演着至关重要的角色&#xff0c;它不仅是现代Web应用程序的基石&#xff0c;还是推动业务发展和提升用户体验的关键技术之一。下面将详细探讨云服务器在Web应用程序中的重要作用及其优势。 首先&#xff0c;云服务器为Web应用程序提供了高度可扩展的…

蜂窝物联粮仓环境在线监测系统,确保粮食安全

在金黄的麦田里&#xff0c;每一粒小麦都承载着农民的辛勤与期待。为了保证这些宝贵粮食的品质与安全&#xff0c;储存环节显得尤为重要。传统的粮仓管理方式已难以满足现代粮食储存的需求&#xff0c;因此&#xff0c;引入智慧粮仓环境监控系统成为了必然的选择。 一、为何需…

谷粒商城 - 树形菜单递归流查询、三级分类数据查询性能优化、Jmter 性能压测

目录 树形分类菜单&#xff08;递归查询&#xff0c;强扩展&#xff09; 1&#xff09;需求 2&#xff09;数据库表设计 3&#xff09;实现 4&#xff09;关于 asSequence 优化 性能压测 1&#xff09;Jmeter 安装使用说明 2&#xff09;中间件对性能的影响 三级分类数…

Python内存优化的实战技巧详解

概要 Python是一种高级编程语言,以其易读性和强大的功能而广受欢迎。然而,由于其动态类型和自动内存管理,Python在处理大量数据或高性能计算时,内存使用效率可能不如一些低级语言。本文将介绍几种Python内存优化的技巧,并提供相应的示例代码,帮助在开发中更高效地管理内…

uniapp启动安卓模拟器mumu

mumu模拟器下载 ADB&#xff1a; android debug bridge &#xff0c; 安卓调试桥&#xff0c;是一个多功能的命令行工具&#xff0c;他使你能够与连接的安卓设备进行交互 # adb连接安卓模拟器 adb connect 127.0.0.1:port # 查看adb设备 adb deviceshubuilderx 有内置的adb&a…

【鸿蒙学习笔记】@Link装饰器:父子双向同步

官方文档&#xff1a;Link装饰器&#xff1a;父子双向同步 目录标题 [Q&A] Link装饰器作用 [Q&A] Link装饰器特点样例&#xff1a;简单类型样例&#xff1a;数组类型样例&#xff1a;Map类型样例&#xff1a;Set类型样例&#xff1a;联合类型 [Q&A] Link装饰器作用…

锂电池寿命预测 | Matlab基于改进的遗传算法优化BP神经网络的锂离子电池健康状态SOH估计

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 主要流程如下: 1、首先提取“放电截止电压时间”作为锂电池间接健康因子&#xff1b; 2、然后引入改进的遗传算法对BP神经网络的模型参数进行优化。 3、最后 NASA 卓越预测中心的锂电池数据集 B0005、B0006、B0007对…

VSCode设置字体大小

方法1&#xff1a;Ctrl 和 Ctrl -&#xff0c;可以控制整个VSCode界面的整体缩放&#xff0c;但是不会调整字体大小 方法2&#xff1a;该方法只能设置编辑器界面的字号&#xff0c;无法改变窗口界面的字号。 &#xff08;1&#xff09;点开左下角如下图标&#xff0c;进入…

【JVM基础篇】Java垃圾回收器介绍

垃圾回收器&#xff08;垃圾回收算法实现&#xff09; 垃圾回收器是垃圾回收算法的具体实现。由于垃圾回收器分为年轻代和老年代&#xff0c;除了G1&#xff08;既能管控新生代&#xff0c;也可以管控老年代&#xff09;之外&#xff0c;新生代、老年代的垃圾回收器必须按照ho…

【Python】组合数据类型:序列,列表,元组,字典,集合

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️Python】 文章目录 前言组合数据类型序列类型序列常见的操作符列表列表操作len()append()insert()remove()index()sort()reverse()count() 元组三种序列类型的区别 集合类型四种操作符集合setfrozens…

tongweb 部署软航流版签一体化应用示例 提示跨域错误CORS ERROR

目录 问题现象与描述 解决办法 原理解析 什么是CORS 浏览器跨域请求限制 跨域问题解决方法 跨域请求流程 浏览器请求分类解析 http请求方法简介 问题现象与描述 重庆软航科技有限公司提供了一套针对针对word、excel等流式文件转换成PDF版式文件并进行版式文件在线签章…

什么是 DDoS 攻击及如何防护DDOS攻击

自进入互联网时代&#xff0c;网络安全问题就一直困扰着用户&#xff0c;尤其是DDOS攻击&#xff0c;一直威胁着用户的业务安全。而高防IP被广泛用于增强网络防护能力。今天我们就来了解下关于DDOS攻击&#xff0c;以及可以防护DDOS攻击的高防IP该如何正确选择使用。 一、什么是…

Apache Seata分布式事务启用Nacos做配置中心

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Seata分布式事务启用Nacos做配置中心 Seata分布式事务启用Nacos做配置中心 项目地址 本文作…

matlab 有倾斜的椭圆函数图像绘制

matlab 有倾斜的椭圆函数图像绘制 有倾斜的椭圆函数图像绘制xy交叉项引入斜线负向斜线成分正向斜线成分 x^2 y^2 xy 1 &#xff08;负向&#xff09;绘制结果 x^2 y^2 - xy 1 &#xff08;正向&#xff09;绘制结果 有倾斜的椭圆函数图像绘制 为了确定椭圆的长轴和短轴的…

复现YOLO_ORB_SLAM3_with_pointcloud_map项目记录

文章目录 1.环境问题2.遇到的问题2.1编译问题1 monotonic_clock2.2 associate.py2.3 associate.py问题 3.运行问题 1.环境问题 首先环境大家就按照github上的指定环境安装即可 环境怎么安装网上大把的资源&#xff0c;自己去找。 2.遇到的问题 2.1编译问题1 monotonic_cloc…