33 包装器

news2024/10/7 9:27:15

c++11
也叫适配器。c++中的function本质是一个类模板,也是一个包装器

为什么需要fuction呢?
当一个类型既可以是函数指针,也可以是仿函数和lambda比倒是,函数指针的类型不好理解,仿函数写起来麻烦,lambda无法拿到类型,有什么办法有统一的函数对象

ret = func(x);
 // 上面func可能是什么呢?那么func可能是函数名?函数指针?函数对象(仿函数对象)?也有可能
是lamber表达式对象?所以这些都是可调用的类型!如此丰富的类型,可能会导致模板的效率低下!
为什么呢?我们继续往下看
template<class F, class T>
 T useF(F f, T x)
 {
 static int count = 0;
 cout << "count:" << ++count << endl;
 cout << "count:" << &count << endl;
 return f(x);
 }
 double f(double i)
 {
 return i / 2;
 }
 struct Functor
 {
 double operator()(double d)
 {
 return d / 3;
 }
 };
 int main()
 {
 // 函数名
cout << useF(f, 11.11) << endl;
 // 函数对象
cout << useF(Functor(), 11.11) << endl;
 // lamber表达式
cout << useF([](double d)->double{ return d/4; }, 11.11) << endl;
 return 0;
 }

通过上面验证,发现useF函数模板实例化了三份
包装器可以解决上述问题

std::function在头文件<functional>
 // 类模板原型如下
template <class T> function;     
// undefined
 template <class Ret, class... Args>
 class function<Ret(Args...)>;
模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参
void swap_func(int& r1, int& r2)
{
	int tmp = r1;
	r1 = r2;
	r2 = tmp;
}

struct Swap
{
	void operator()(int& r1, int& r2)
	{
		int tmp = r1;
		r1 = r2;
		r2 = tmp;
	}
};

int main()
{
	int x = 0, y = 1;
	cout << x << " " << y << endl;

	auto swaplambda = [](int& r1, int& r2) {
		int tmp = r1;
		r1 = r2;
		r2 = tmp;
	};

	function<void(int&, int&)> f1 = swap_func;
	f1(x, y);
	cout << x << " " << y << endl << endl;

	function<void(int&, int&)> f2 = Swap();
	f2(x, y);
	cout << x << " " << y << endl << endl;

	function<void(int&, int&)> f3 = swaplambda;
	f3(x, y);
	cout << x << " " << y << endl << endl;

	// 11:40继续
	map<string, function<void(int&, int&)>> cmdOP = {
		{"函数指针", swap_func},
		{"仿函数", Swap()},
		{"lambda", swaplambda},
	};

	cmdOP["函数指针"](x, y);
	cout << x << " " << y << endl << endl;

	cmdOP["仿函数"](x, y);
	cout << x << " " << y << endl << endl;

	cmdOP["lambda"](x, y);
	cout << x << " " << y << endl << endl;

	return 0;
}

类函数的包装

类函数需要指定域,成员函数第一个参数是this指针,需要传入

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)> f1 = &Plus::plusi;
	cout << f1(1, 2) << endl;

	//成员函数第一个参数默认是this指针
	function<double(Plus*, double, double)> f2 = &Plus::plusd;
	Plus ps;
	cout << f2(&ps, 1.1, 2.2) << endl;
	//和上面类似
	function<double(Plus, double, double)> f3 = &Plus::plusd;
	cout << f3(Plus(), 1.11, 2.22) << endl;

	return 0;
}

类的函数调用每次都要写一个类,有点麻烦,有什么办法省略?

改造题目
https://leetcode.cn/problems/evaluate-reverse-polish-notation/submissions/
在这里插入图片描述

class Solution {
public:
    int evalRPN(vector<string>& tokens) {

        stack<int> st;
        for (auto str:tokens)
        {
            if (str == "+" || str == "-" || str == "*" || str == "/")
            {
                int right = st.top();
                st.pop();
                int left = st.top();
                st.pop();

                int ret = 0;
                switch(str[0])
                {
                    case '+':
                        ret = left + right;
                        st.push(ret);
                        break;
                        case '-':
                       ret = left - right;
                        st.push(ret);
                        break;
                        case '*':
                         ret = left * right;
                        st.push(ret);
                        break;
                        case '/':
                        ret = left / right;
                        st.push(ret);
                        break;
                }
            }else
            {
                st.push(stoi(str));
            }
        }

        return st.top();
    }
};

用包装器修改上面:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {

        stack<int> st;
        map<string, function<int(int, int)>> cmdop = 
        {
            {"+", [](int x, int y){return x + y;}},
            {"-", [](int x, int y){return x - y;}},
            {"*", [](int x, int y){return x * y;}},
            {"/", [](int x, int y){return x / y;}}
        };

        for (auto str:tokens)
        {
            if (cmdop.count(str))
            {
                int right = st.top();
                st.pop();
                int left = st.top();
                st.pop();

                st.push(cmdop[str](left, right));
            }
            else
            {
                st.push(stoi(str));
            }
        }

        return st.top();
    }
};

bind
std::bind函数定义在头文件中,是一个函数模板,就像一个函数包装器(适配器),接受一个调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。一般而言,我们用它把一个原本接收n个参数的函数fn,通过绑定一些参数,返回一个接收m个(m可以大于n,但没意义)参数的新函数。同时,还可以调整参数顺序

// 原型如下:
template <class Fn, class... Args>
 /* unspecified */ bind (Fn&& fn, Args&&... args);
 // with return type (2) 
template <class Ret, class Fn, class... Args>
 /* unspecified */ bind (Fn&& fn, Args&&... args);

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

//绑定第一个参数
function<double(double, double)> f4 = bind(Plus::plusd, Plus(), placeholders::_1, placeholders::_2);
cout << f4(1.11, 2.22) << endl;
int Sub(int a, int b)
{
	return a - b;
}
//参数写死
function<int(int)> f6 = bind(Sub, 20, placeholders::_1);
cout << f6(5) << endl;

int Sub2(int a, int b, int c)
{
	return a - b;
}
//中间写死
function<int(int, int)> f7 = bind(Sub2, placeholders::_1, 20, placeholders::_2);
cout << f7(5, 6) << endl;
return 0;

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

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

相关文章

前端基础:CSS(篇二)

目录 盒子 模型&#xff08;box-model&#xff09; 盒子 模型-内容区 代码 运行 盒子 模型-内边距 代码 运行 盒子 模型-边框 代码 运行 盒子 模型-外边距 代码 运行 清除浏览器的默认样式 代码 运行 盒子模型练习 代码 运行 ​编辑 文档流 浮…

IO模型与多路复用

前言 在Linux中有一句经典台词&#xff1a;“Linux一切皆文件”。IO操作是与文件进行交流的唯一方式&#xff0c;也就是说这是与Linux系统交流的唯一手段。就如同人与人之间的交流&#xff0c;如果我们连交流的方式都不甚了解&#xff0c;交流的效率就会变得低下。操作系统也是…

计算机专业的概念需要拓宽|终身学习之旅利:用FlowUs打造个性化学习记录知识库

计算机相关专业长期以来一直是热门选择&#xff0c;这主要得益于技术的快速发展和广泛的应用场景。随着AI技术的不断进步&#xff0c;这一趋势在未来几年内仍有望持续。以下是从不同角度对这个问题的分析&#xff1a; 从AI发展的角度&#xff1a; 技术革新&#xff1a;AI技术…

2024年地球生态学与绿色发展国际会议 (EEGD 2024)

2024年地球生态学与绿色发展国际会议 (EEGD 2024) International Conference on Earth Ecology and Green Development in 2024 【重要信息】 大会地点&#xff1a;济南 大会官网&#xff1a;http://www.iceegd.com 投稿邮箱&#xff1a;iceegdsub-conf.com 【注意&#xff1a…

新赛季守望先锋2延迟高怎么办?快速降低守望先锋2延迟的小妙招

随着守望先锋2新赛季的开启&#xff0c;这款游戏又引入了大量全新内容&#xff0c;包括新地图、新神话皮肤等。而之前在预告片最后出现的《变形金刚》系列标志性的变形音效&#xff0c;表明在本赛季将与《变形金刚》系列展开联动更是吸引了不少玩家的关注。因为7月9日变形金刚联…

安装Rabbitmq遇到的坑

&#xff01;&#xff01;&#xff01;一定要对号版本号 不同的虚拟机unbontu、cetenos和不同的erlang和不同的rabbitmq之间要对应下载对应版本 下面给出我的版本centos7erlangrabbitmq 分割线 安装好后&#xff0c;如果在虚拟机的服务器上可以打开&#xff0c;在本地浏览器…

【基于R语言群体遗传学】-3-计算等位基因频率

书接上文&#xff0c;我们讲完了哈代温伯格基因型频率&#xff0c;也使用数据进行了拟合&#xff0c;那么接下来就是考虑一些计算的问题&#xff1a; 【基于R语言群体遗传学】-1-哈代温伯格基因型比例-CSDN博客 【基于R语言群体遗传学】-2-模拟基因型&#xff08;simulating …

Hubstudio指纹浏览器:海外代理IP新选择,IPXProxy为何备受推崇?

许多人都会把Hubstudio指纹浏览器和代理IP进行搭配使用&#xff0c;为了保证网络操作的顺利进行&#xff0c;例如亚马逊的多账号管理。那有没有好用的海外代理IP呢&#xff0c;如何在Hubstudio指纹浏览器中使用代理IP呢&#xff1f; 下面就给大家推荐好用的一家海外IP代理&…

收银系统源码-千呼新零售2.0

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

SMARTFORMS

page&#xff08;节点&#xff09;-> wondows(容器)

AI网络爬虫004:从东方财富网批量获取上市公司的全部新闻资讯

文章目录 一、目标二、输入内容三、输出内容一、目标 用户输入一个上市公司名称,然后程序自动从东方财富网批量获取上市公司的全部新闻资讯 查看相关元素在源代码中的位置: 新闻标题:<a href="http://finance.eastmoney.com/a/202405233084538683.html" targ…

Pytest+Allure+Yaml+PyMsql+Jenkins+Gitlab接口自动化(四)Jenkins配置

一、背景 Jenkins&#xff08;本地宿主机搭建&#xff09; 拉取GitLab(服务器)代码到在Jenkins工作空间本地运行并生成Allure测试报告 二、框架改动点 框架主运行程序需要先注释掉运行代码&#xff08;可不改&#xff0c;如果运行报allure找不到就直接注释掉&#xff09; …

以责任铸就品牌,以行动推动社会进步

成都树莓集团&#xff0c;作为数字产业生态链的积极建设者&#xff0c;始终将履行社会责任作为企业发展的核心要义。我们深知&#xff0c;企业的成功不仅仅在于经济效益的取得&#xff0c;更在于对社会的贡献与回馈。 一、履行社会责任的实践 1、倡导绿色、低碳、可持续的发展…

Redis 7.x 系列【13】数据类型之地理位置(Geospatial)

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 常用命令2.1 GEOADD2.2 GEODIST2.3 GEORADIUS2.4 GEOPOS2.5 GEORADIUSBYMEM…

C++ 和C#的差别

首先把眼睛瞪大&#xff0c;然后憋住一口气&#xff0c;读下去&#xff1a; 1、CPP 就是C plus plus的缩写&#xff0c;中国大陆的程序员圈子中通常被读做"C加加"&#xff0c;而西方的程序员通常读做"C plus plus"&#xff0c;它是一种使用非常广泛的计算…

​RAG与LLM原理及实践(8)--- Chroma 应用场景及限制

前言 通过前面几节的介绍&#xff0c;你应该对Chroma的运作原理有相当透彻的理解。Chroma的设计正如之前描述的&#xff1a; Chroma提供的工具&#xff1a; 存储文档数据和它们的元数据&#xff1a;store embeddings and their metadata 嵌入&#xff1a;embed documents an…

仓库管理系统25--数据导出

原创不易&#xff0c;打字不易&#xff0c;截图不易&#xff0c;多多点赞&#xff0c;送人玫瑰&#xff0c;留有余香&#xff0c;财务自由明日实现 1、添加用户控件 <UserControl x:Class"West.StoreMgr.View.DataExportView"xmlns"http://schemas.microsof…

融云 CEO 董晗获颁 EqualOcean「2024 出海全球化服务 30 人」

6 月 26 日-27 日&#xff0c;EqualOcean 全球化百人论坛 &#xff08;GGF2024&#xff09;及颁奖盛典在深圳举办&#xff0c;融云 CEO 董晗荣登“2024 出海全球化服务 30 人”榜单。 作为全球商业信息平台和智库&#xff0c;EqualOcean 设立“出海全球化服务 30 人榜单”&am…

u盘里的数据全部不见了怎么恢复?这些方法你试过吗

在快节奏的工作和生活中&#xff0c;U盘作为我们随身携带的数据存储工具&#xff0c;承载了无数重要的文件和资料。然而&#xff0c;有时我们会突然发现U盘里的数据全部不见了&#xff0c;这无疑会给我们带来巨大的困扰和焦虑。面对这种情况&#xff0c;不要慌张&#xff0c;本…

2小时动手学习扩散模型(pytorch版)【入门版】【代码讲解】

2小时动手学习扩散模型&#xff08;pytorch版&#xff09; 课程地址 2小时动手学习扩散模型&#xff08;pytorch版&#xff09; 课程目标 给零基础同学快速了解扩散模型的核心模块&#xff0c;有个整体框架的理解。知道扩散模型的改进和设计的核心模块。 课程特色&#xf…