泛型编程-常用模板

例举C++11 常用模板

一.变参模板

        当我们需要处理不定数量的参数时,C++的变参模板(variadic templates)提供了一种灵活的解决方案。变参模板允许我们定义接受任意数量参数的函数或类模板。

        变参模板主要分为三部分:

        模板形参包(固定类型模板形参包、类型模板形参包、模板模板形参包)、函数形参包、形参展开使用。

1. 变参数模板的基础-模板形参包
1.1 非类型模板形参包(c++17引入)

        非类型(固定)模板形参包的主要用途是在编写通用代码时,能够接受任意数量的非类型参数,并对它们进行处理。这样可以实现更灵活的模板编程,提高代码的复用性和可扩展性。

使用语法:

template<类型 ... args>

 注意:这个类型是有限制的,只能是整型、指针、引用

使用折叠语法

template <int... Values>
constexpr int sum() {return (Values + ...);
}int main()
{int result = sum<1, 2, 3, 4, 5>();std::cout << result << std::endl;
}
1.2 类型模板形参包

类型模板形参包语法:

typename|class ... Args

使用: 

#include <iostream>
#include <memory>using namespace std;int sum()  //没有参数的时候
{return 0;
}template<typename T, typename... Args>  
auto sum(T first, Args... args)
{return (first) + sum(args...);
}int main()
{cout<<"sum:"<<sum(1,2,3,4,5)<<endl;return 0;
}

typename... Args:这是一个模板参数包(template parameter pack)的语法,用于接受任意数量的类型参数,并将它们打包成一个参数包 Args

Args... rest:这是一个函数参数包(function parameter pack)的语法,用于接受任意数量的函数参数,并将它们打包成一个参数包 rest

rest...:这是一个展开语法(unpacking syntax),用于将参数包 rest 展开为一系列参数。

在示例中,Args 表示一组类型参数,

                  rest 表示一组函数参数,

                  rest... 将参数包 rest 展开为一系列参数,然后作为新的参数传递给函数。

 1.3 模板模板形参包

        待补充。

2.模板形参包延申-函数形参包

函数形参包的语法:

Args ... args

Args...代表形参包类型,这个类型就是模板形参包里面声明的类型,args就是函数的形参名称了,是可以自定义的。 

        除了非类型的模板形参包因为类型固定且是具体的值,不能作为函数形参包以外,类型模板形参包和模板模板形参包因为声明的都是类型,所以他们是可以用作函数形参的类型的。

        上述已经举例,不做过多说明。

3.模板形参包的展开方法 

形参包展开语法:

模式 ...

二.别名模板-using

        using 关键字在 C++11 之前,using 关键字主要用于类型别名的声明。例如:

typedef int myInt;
using myInt = int;

        在 C++11 中,using 关键字引入了新的类型别名声明语法,包括别名模板、类型别名模板、

特化别名模板、特化类型别名mo'b

#include <iostream>
#include <vector>// 别名模板
template <typename T>
using myAlias = std::vector<T>;// 类型别名模板
template <typename T>
struct myTypeAlias {using type = std::vector<T>;
};// 特化别名模板
template <>
using myAlias<int> = std::vector<int>;// 特化类型别名模板
template <>
struct myTypeAlias<int> {using type = std::vector<int>;
};int main() {myAlias<double> myVector1;  // 使用别名模板myVector1.push_back(1.23);myVector1.push_back(4.56);std::cout << "Size of myVector1: " << myVector1.size() << std::endl;typename myTypeAlias<double>::type myVector2;  // 使用类型别名模板myVector2.push_back(7.89);myVector2.push_back(0.12);std::cout << "Size of myVector2: " << myVector2.size() << std::endl;myAlias<int> myVector3;  // 使用特化的别名模板myVector3.push_back(1);myVector3.push_back(2);std::cout << "Size of myVector3: " << myVector3.size() << std::endl;typename myTypeAlias<int>::type myVector4;  // 使用特化的类型别名模板myVector4.push_back(3);myVector4.push_back(4);std::cout << "Size of myVector4: " << myVector4.size() << std::endl;return 0;
}

三.tuple 类模板

        在C++11 引用std::tuple 类模板,它是一个通用的元组类,可以存储多个不同类型的值。需要注意的是,std::tuple 是一个不可变的数据结构,一旦创建后,其元素的值是不可修改的。

#include <iostream>
#include <memory>
#include <tuple>using namespace std;struct MyStruct {int value;double weight;string str1;
};using MyCustomStruct = MyStruct;int main()
{//通过get读取tuple<int, double, string> mytuple(1,99.9,"hello");cout<<"mytuple.get:"<<get<0>(mytuple)<<endl;cout<<"mytuple.get:"<<get<1>(mytuple)<<endl;cout<<"mytuple.get:"<<get<2>(mytuple)<<endl;cout<<"sizeof(tuple)"<<sizeof(mytuple)<<endl;  //48cout<<"sizeof(int)"<<sizeof(get<0>(mytuple))<<endl; //4cout<<"sizeof(double)"<<sizeof(get<1>(mytuple))<<endl; //8 cout<<"sizeof(string)"<<sizeof(get<2>(mytuple))<<endl; //32cout<<"sizeof(MyStruct)"<<sizeof(MyCustomStruct)<<endl; //48//通过 结构化绑定解包 tuple 中的值auto[intVal, douVal, strVal] = mytuple;cout<<"intVal:"<<intVal<<endl;cout<<"douVal:"<<douVal<<endl;cout<<"strVal:"<<strVal<<endl;//赋值auto mytuple2 = make_tuple(99, get<2>(mytuple), "nihao");
}

四.bind类模板

         std::bind 是 C++ 标准库中的一个函数模板,用于创建函数对象(也称为绑定器),将参数绑定到函数中。它的使用场景包括:

  •  绑定函数对象:std::bind可以将一个函数对象与其参数绑定,创建一个新的可调用对象。这样,我们可以在稍后的时间点调用这个可调用对象,而不需要再次提供参数。这对于延迟执行函数或将函数作为参数传递非常有用。、
  • 重排参数顺序:std::bind可以通过重新排列参数的顺序,将函数的参数与绑定的参数进行匹配。这使得我们可以在调用时以不同的顺序提供参数,而不必更改函数的定义。
  • 固定部分参数:std::bind可以将函数的部分参数固定下来,而不需要提供完整的参数列表。这样,我们可以创建一个新的函数对象,该对象只需要提供剩余的参数即可完成调用。
  • 占位符参数:std::bind使用std::placeholders::_1std::placeholders::_2等占位符参数,可以在绑定函数对象时指定参数的位置。这使得我们可以在调用时动态地提供参数,而不需要提前确定参数
1.bind绑定非成员函数
#include <iostream>
#include <functional>using namespace std;int sum(int a, int b)
{return a + b;
}int main()
{auto func = std::bind(sum, 1, placeholders::_1);cout<<"sum:"<<func(2)<<endl;
}
2.bind绑定成员函数 
#include <iostream>
#include <functional>using namespace std;class MyClass {
public:int sum(int a, int b) {return a+ b;}
};int main()
{MyClass obj;auto func = std::bind(&MyClass::sum, &obj, 1, placeholders::_1);cout<<"sum:"<<func(2)<<endl;
}
3.bind函数使用注意
  • bind函数无法绑定一个重载函数的参数,必须显示的绑定重载函数版本
//有这样的重载函数
int good(int);
double good(double);
auto result = std::bind(good,_1);      //错误形式,不知道调用哪一个good函数
//正确的做法,但是比较复杂
auto result_1 = std::bind(double(*)(double)good, _1); 
//这是更好的方式
auto result_2 = std::bind<double>(good, _1);   //指定函数的返回类型

五.function类模板

        std::function是一个通用的函数封装器,可以用来存储、复制和调用任何可调用对象(函数、函数指针、成员函数指针、函数对象等)。它可以用于实现回调机制、函数参数传递等。

        std::function不管其实例类型是什么样的,其调用形式是一样的,如下:

返回值类型(实参1,实参2,实参3...)

使用方法(列举所有函数调用方法):

#include <iostream>
#include <functional>using namespace std;typedef function<int(int)> Functional;int funcValue(int x) 
{return x;
}//仿函数
class Functor
{
public:int operator()(int a){return a;}
};//类的成员函数和静态函数
class Func
{
public:int func(int a){return a;}static int staticFunc(int a){return a;}
};int main()
{//普通函数调用cout<<"value:"<<funcValue(1)<<endl;//封装普通函数Functional obj = funcValue;cout<<"obj.value:"<<obj(2)<<endl;//lamda表达式auto lambObj = [](int a)->int{return a;};cout<<"lambObj.value"<<lambObj(3)<<endl;//仿函数Functor obj1;cout<<"obj1.value:"<<obj1(4)<<endl;//类成员函数Func fun;cout<<"func.value:"<<fun.func(5)<<endl;//类静态成员函数cout<<"staticFunc.value:"<<Func::staticFunc(6)<<endl;//通过bind绑定auto bindfun = bind(&Func::func, &fun, placeholders::_1);cout<<"bindfun.value:"<<bindfun(7)<<endl;
}

六.智能引用

        智能引用是一种用于管理资源的对象。它们提供了对资源的安全访问,并确保资源在不再需要时被正确释放,使用智能引用的好处:

  1. 包装你给的对象引用
  2. 传参数时, 消除复杂对象的拷贝代价
  3. 不可拷贝对象转换为可拷贝对象(noncopyable, singleton之类的)

对于第二点:

#include <iostream>
#include <functional>using namespace std;template<class T>
class ref_wra
{
public:explicit ref_wra(T &_t):t_(&_t){}operator T&() const{return *t_;}  //将对象转换为T&的引用  T& get() const{return *t_;}T* get_ptr() const{return t_;}private:T *t_;
};void add(int& num) {num++;
}int main()
{int dight =  10;ref_wra<int> ref(dight); //隐式转换operator T&()cout<<"1.通过隐式转换,使用引用访问原始对象:"<<ref<<endl;int value = ref; //隐式转换operator T&()cout<<"2.通过隐式转换,使用引用访问原始对象:"<<value<<endl;ref.get() = 11;cout<<"3.访问原始对象:"<<ref<<endl;int *ptr = ref.get_ptr();cout<<"4.内部维护指针:"<<ref<<endl;add(ref);cout<<"5.通过传引用:"<<ref<<endl;return 0;
}

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

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

相关文章

Transformers 2023年度回顾 :从BERT到GPT4

人工智能已成为近年来最受关注的话题之一&#xff0c;由于神经网络的发展&#xff0c;曾经被认为纯粹是科幻小说中的服务现在正在成为现实。从对话代理到媒体内容生成&#xff0c;人工智能正在改变我们与技术互动的方式。特别是机器学习 (ML) 模型在自然语言处理 (NLP) 领域取得…

【仙丹秘法】如何炼制一颗稳定的仙丹

提示词始终保持不变 1&#xff1a;收集素材 制作lora_v1 2: 制作lora_v1 产生 1个人物 含 你想要的服装 导入 pose_1 到 control 1 生成人物 (white_background:1.1),front view,1boy,blue sleeveless t-shirt,blue shorts,detailed eyes,best quality,masterpiece,high res…

第三站:C/C++基础-二维数组

二维数组的概念 一维数组本身是多个大小相同的内存块,从0开始逐渐递增所组成的在横向上的有序"组合", 二维数组就是很多个一维数组在纵向上的组合,每一个一维数组就是二维数组在纵向上的从0开始的逐渐递增的一个单位,(所以一维数组在二维数组的基础上,每一个内存块…

L1-010 比较大小(Java)

题目 本题要求将输入的任意3个整数从小到大输出。 输入格式: 输入在一行中给出3个整数&#xff0c;其间以空格分隔。 输出格式: 在一行中将3个整数从小到大输出&#xff0c;其间以“->”相连。输入样例: 4 2 8 输出样例: 2->4->8解题思路 输入三个整数&#xff1a;…

Spring 基于注解的AOP见解4

5.基于注解的AOP配置 5.1创建工程 5.1.1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&…

SUDA-计算机网路-期末复习提纲

写在前面 帮苏大的同学整理的计网复习材料&#xff0c;用的是他们老师划定的范围。 1.负责互联网协议开发、标准制定、地址分配的国际组织名称及其主要职责 (1) 地址支持组织&#xff08;ASO&#xff09;负责IP地址系统的管理。 (2) 域名支持组织&#xff08;DNSO&#xff09;…

LeetCode(242)有效的字母异位词⭐

给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true示例 2: 输…

更新 torchtext 造成的torch版本不匹配的问题

更新 torchtext 造成的torch版本不匹配的问题 - pip 原来的版本配置 cuda11.6 torch-GPU 1.13.1 如果直接pip update torchtext 会卸载原来的torch然后默认安装CPU版本&#xff0c;很烦。网上的各种方法都是推荐conda.但是我一直都是pip。因此考虑pip 的解决办法。 解决办…

【2023 CSIG垂直领域大模型】大模型时代,如何完成IDP智能文档处理领域的OCR大一统?

目录 一、像素级OCR统一模型&#xff1a;UPOCR1.1、为什么提出UPOCR&#xff1f;1.2、UPOCR是什么?1.2.1、Unified Paradigm 统一范式1.2.2、Unified Architecture统一架构1.2.3、Unified Training Strategy 统一训练策略 1.3、UPOCR效果如何&#xff1f; 二、OCR大一统模型前…

kdump安装及调试策略

本文基于redhat系的操作系统&#xff0c;debian系不太一样&#xff0c;仅提供参考 1.kdump的部署 注&#xff1a;一般很多操作系统在安装时可默认启动kdump。 &#xff08;1&#xff09;需要的包 yum install kexec-tools crash kernel-debuginfo &#xff08;2&#xff0…

《堆排序》与《Top—k》

目录 ​编辑 前言&#xff1a; 关于《堆排序》&#xff1a; 第一步&#xff1a;建堆 第二步&#xff1a;排序 《Top—K问题》 关于Top—k问题&#xff1a; 前言&#xff1a; 我们在前面的blog中&#xff0c;对于《堆》已经有了初步的概念&#xff0c;那么接下来我们可以…

机器学习简答题

1、请简述人工智能和机器学习&#xff0c;深度学习的关系&#xff1f; 机器学习是人工智能的一个实现途径。深度学习是机器学习的一个方法发展而来 2、根据数据集组成不同&#xff0c;通常可以把机器学习算法分为哪四类&#xff1f; 监督学习、无监督学习、半监督学习、强化…

搭建Python(3.7及以上版本)环境并安装DashScope SDK报错

搭建Python3.7及以上版本环境并安装DashScope SDK报错 搭建Python环境这里忽略&#xff0c;搭建好环境后安装 pip install dashscope但是会报错&#xff0c;如下所示&#xff1a; ERROR: Could not find a version that satisfies the requirement dashscope (from versions: …

C++中,Lambda表达式和std::function的作用及区别

Lambda表达式和std::function在C中都用于处理函数对象&#xff0c;但它们有不同的用途和使用场景。 Lambda表达式的作用是定义一个匿名函数&#xff0c;可以在需要函数对象的地方直接使用。Lambda表达式通常用于简短的函数逻辑&#xff0c;特别适合用于一些需要定义临时函数的…

flex布局(2)

五、优缺点 优点&#xff1a; 简单易用&#xff1a;Flex布局使用简单&#xff0c;只需通过设置容器的属性即可实现弹性布局&#xff0c;无需复杂的计算和调整。自适应性&#xff1a;Flex布局可以根据容器的大小自动调整元素的位置和大小&#xff0c;适应不同的屏幕尺寸和设备…

3.5 RESOURCE ASSIGNMENT

一旦内核启动&#xff0c;CUDA运行时系统将生成相应的线程网格。正如上一节所讨论的&#xff0c;这些线程被分配给逐个块执行资源。在当前一代硬件中&#xff0c;执行资源被组织成流式多处理器&#xff08;SM&#xff09;。图3.12说明可以为每个SM分配多个线程块。每个设备都对…

uniapp中uview组件库中丰富的LineProgress 线形进度条 的使用方法

目录 平台差异说明 #基本使用 #设置进度条动画效果 #设置进度条内部显示百分比值 #修改进度条的样式 #API #Props #Slots 平台差异说明 AppH5微信小程序支付宝小程序百度小程序头条小程序QQ小程序√√√√√√√ #基本使用 通过percent设置当前的进度值&#xff0c;该…

计算机视觉下的数据增强代码实现

数据增强的实现 使用经典的pytorch框架下的torchvision.transformers对计算机视觉进行增强的代码实现。 使用下面的图像进行数据增强&#xff0c;相应的效果图如下所示&#xff01; 导包 import os import PIL.Image as Image from torchvision import transforms as transfor…

微信小程序的登录模块实现

用户联动微信小程序。相关的实现层代码 发送url请求。 /*** 登录验证** param code 临时登录码* return */Overridepublic Map<String, Object> checkLogin(String code) {String url "https://api.weixin.qq.com/sns/jscode2session?appid" appid "…

RT-Thread 线程间同步 信号量

线程间同步 在多线程实时系统中&#xff0c;一项工作的完成往往可以通过多个线程协调的方式共同来完成。 例如一项工作中的两个线程&#xff1a;一个线程从传感器中接收数据并且将数据写到共享内存中&#xff0c;同时另一个线程周期性地从共享内存中读取数据并发送出去显示&a…