“编写一次,无限应用:深入理解C++模板“

在这里插入图片描述

🚀write in front🚀
📜所属专栏: C++学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言
  • 一.静态对象和类型的混淆:
  • 二.模板的特化:
    • 1.函数模板特化:
    • 2.类模板特化:
      • 全特化:
      • 偏特化:
        • a.特化部分参数:
        • b.参数的进一步修饰:
      • 具体使用场景:
  • 三.模板分离编译
    • 3.1 什么是分离编译
    • 3.2 模板的分离编译
    • 3.3 解决方法
  • 总结模板的优缺点:

前言

  在了解完模板初阶以后,我们来学习进阶的知识!

一.静态对象和类型的混淆:

  我们先来看看这个代码:

template<class Container>
void print(const Container &v)
{Container::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;
}void test1()
{
vector<int> vv;
print(vv);
}

  这段代码在运行的时候会出错,可是为什么呢?

我们在类里面用::访问的时候有两种情况:

  1. 静态成员对象
  2. 类型

  编译器不知道这里的访问是静态对象还是类型名,所以这里就会报错。

那么怎么解决呢?

  我们只要在类型名之前加一个typename或者直接用auto来表示类型就可以了。

  所以,在类模板或者函数模板中,当你引用模板参数的嵌套类型时,最好在前面加上 typename,这样可以消除歧义,使代码更具可读性,也有助于编译器正确地解析代码。

二.模板的特化:

  通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板:

// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
int main()
{
cout << Less(1, 2) << endl; // 可以比较,结果正确
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less(d1, d2) << endl; // 可以比较,结果正确
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; // 可以比较,结果错误
return 0;
}

  如果我们通过指针比大小,那肯定是错误的。此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化类模板特化

1.函数模板特化:

  我们先来看看一个比较大小的函数

// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}

  如果此时我们通过指针想要比较他们的大小时,就可在这个函数的基础上特化出一个新模板:

template<>
bool Less<int*>(int* x, int * y)
{return *x < *y;
}

  但是对于函数模板的特化,我们可以直接重新写一个,就没必要在特化一个新的了。
  当然,我们也可以通过胁制类型来特化一个模板函数:

template<class T>
bool Less(T* x, T* y)
{return *x < *y;
}

重点

  1. 必须要先有一个基础的函数模板
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参表:必须要和模板函数的基础参数类型完全相同(别加const就可以了)如果不同编译器可能会报一些奇怪的错误。

2.类模板特化:

  类模板特化分为两种:全特化和偏特化

全特化:

  全特化即是将模板参数列表中所有的参数都确定化:

template<class T1, class T2>
class Data
{
public:
Data() {cout<<"Data<T1, T2>" <<endl;}
private:
T1 _d1;
T2 _d2;
};
template<>
class Data<int, char>
{
public:
Data() {cout<<"Data<int, char>" <<endl;}
private:
int _d1;
char _
};
void TestVector()
{
Data<int, int> d1;
Data<int, char> d2;
}

  通过运行发现,如果有符合的全特化的类,那么就不用在通过模板实例化一份类出来。

偏特化:

  偏特化也有两种情况:

a.特化部分参数:

template<class T1>
class Data<T1, double>
{
public:Data() { cout << "Data<T1, double>" << endl; }
private:
};

  这样的偏特化,就将第二个参数定死为double类型,只要第二个类型为double,而且没有更具体的类,我们就会调用这个类。

b.参数的进一步修饰:

template<class T1, class T2>
class Data<T1*, T2*>
{
public:Data() { cout << "Data<T1*, T2*>" << endl; }
private:
};template<class T1, class T2>
class Data<T1&, T2&>
{
public:Data() { cout << "Data<T1&, T2&>" << endl; }
private:
};

  在类后面对参数进行限制,第一个偏特化限制为指针,第二个偏特化限制为引用。

具体使用场景:

  我们通过算法库里的sort函数排序来调用仿函数的例子来使用一下类模板的特化:

#include<vector>
#include <algorithm>
template<class T>
struct Less
{
bool operator()(const T& x, const T& y) const
{
return x < y;
}
};
int main()
{
Date d1(2022, 7, 7);
Date d2(2022, 7, 6);
Date d3(2022, 7, 8);
vector<Date> v1;
v1.push_back(d1);
v1.push_back(d2);
v1.push_back(d3);
// 可以直接排序,结果是日期升序
sort(v1.begin(), v1.end(), Less<Date>());
vector<Date*> v2;
v2.push_back(&d1);
v2.push_back(&d2);
v2.push_back(&d3);
// 可以直接排序,结果错误日期还不是升序,而v2中放的地址是升序
// 此处需要在排序过程中,让sort比较v2中存放地址指向的日期对象
// 但是走Less模板,sort在排序时实际比较的是v2中指针的地址,因此无法达到预期
sort(v2.begin(), v2.end(), Less<Date*>());
return 0;
}

  通过观察上述程序的结果发现,对于日期对象可以直接排序,并且结果是正确的。但是如果待排序元素是指针,结果就不一定正确。因为:sort最终按照Less模板中方式比较,所以只会比较指针,而不是比较指针指向空间中内容,此时可以使用类版本特化来处理上述问题

// 对Less类模板按照指针方式特化
template<>
struct Less<Date*>
{
bool operator()(Date* x, Date* y) const
{
return *x < *y;
}
};

特化之后,在运行上述代码,就可以得到正确的结果

三.模板分离编译

3.1 什么是分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

3.2 模板的分离编译

假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

// a.h
template<class T>
T Add(const T& left, const T& right);
void func1(int a,int b)void func2(double a,double b)// a.cpp
template<class T>
T Add(const T& left, const T& right)
{
return left + right;
}
void func1(int a,int b)
{
return a+b;
}
void func2(double a,double b)
{
return a+b;
}
// main.cpp
#include"a.h"
int main()
{
func1(1,2);
func2(1.0,2.0);
Add("abc","def");
return 0;
}

  在分析前我们先来回顾一下编译链接的相关知识:
在这里插入图片描述
在这里插入图片描述

在编译运行时我们会发现:

  • func1链接查到了
  • func2链接查找不到,因为只有声明没有定义
  • Add链接查找不到,但是我们定义了呀

  那么为什么会出现这样的情况呢?其实啊,我们发现func1可以编译成功,是因为他是一段“具体”的函数,而我们知道,模板实例化是在编译的时候进行的,Add函数在编译的时候只是说可以在头文件找到他的声明,但是并没有对这个模板实例化。所以在链接的时候我们不能找到实例化的函数地址与之对应,链接就会报错。

3.3 解决方法

  1. 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。
  2. 模板定义的位置显式实例化。这种方法不实用,不推荐使用:
    比如在刚刚的a.cpp文件下加一个:
template
Add<string>;

总结模板的优缺点:

【优点】

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性(适配器和仿函数的使用)

【缺陷】

  1. 模板会导致代码膨胀问题,也会导致编译时间变长
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
C语言学习
算法
智力题
初阶数据结构
Linux学习
C++学习
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

Java多线程(3)---锁策略、CAS和JUC

目录 前言 一.锁策略 1.1乐观锁和悲观锁 ⭐ 两者的概念 ⭐实现方法 1.2读写锁 ⭐概念 ⭐实现方法 1.3重量级锁和轻量级锁 1.4自旋锁和挂起等待锁 ⭐概念 ⭐代码实现 1.5公平锁和非公平锁 1.6可重入锁和不可重入锁 二.CAS 2.1为什么需要CAS 2.2CAS是什么 ⭐CAS…

互联网DPI

DPI是Deep packet inspection. 基于数据包的深度检测技术&#xff0c;针对不同的网络应用层载荷&#xff08;例如HTTP、DNS等&#xff09;进行深度检测&#xff0c;通过对报文的有效载荷检测决定其合法性。&#xff08;From Baidu&#xff09; 深度检测是与普通的报文分析层次…

模糊PID(模糊规则表)

模糊PID的模糊化相关内容,请参看下面的博客文章: PLC模糊控制模糊PID(梯形图实现+算法分析)_RXXW_Dor的博客-CSDN博客博途PLC的模糊PID控制详细内容请查看下面的博客文章:Matlab仿真+博途PLC模糊PID控制完整SCL源代码参考(带模糊和普通PID切换功能)_博途怎么实现模糊pid_…

如何取消Barracuda Reputation的IP 黑名单?

客户来信反映说邮件发送失败&#xff0c;退信内容如下&#xff1a; reason: 554 Service unavailable; Client host [*********邮件服务器] blocked using Barracuda Reputation; http://bbl.barracudacentral.com/q.cgi?ip116.231.5.113) 解决方法参考如下说明: 1.当你采用ou…

win10 高DPI 高分屏 解决模糊问题的方法

本人使用的是 win10 1809的版本 使用高分辨率的显示器时&#xff0c;发现打开部分win7软件很模糊&#xff0c;分分钟亮瞎眼&#xff0c;在网上找遍了相关的设置方法&#xff08;比如使用字体修改软件&#xff0c;使用修改DPI修改软件等&#xff09;&#xff0c;没有得到我要的理…

【技巧】修改windows10在高分屏下的应用的dpi

我使用的是surface pro3&#xff0c;拥有2K的分辨率。 同时&#xff0c;我很热衷新事物所以&#xff0c;我使用了windows10 的最新版&#xff0c;并且启用了高dpi设置&#xff08;150左右&#xff09;。 之后就发现一些老软件如photoshop、Articulate Storyline、百度网盘等应…

第十七届全国大学生智能车竞赛华南赛区报名信息

学校组别队名组员指导教师 华南理工大学四轮电磁组华工旋风队王熙来陈安邓晓燕   艾一帆     张家瑜   四轮摄像头组华工白弧队黄岳鹏陈安邓晓燕   梁健铭     张武江   多车编队组华工冰魄队李茂霖陈安邓晓燕   亢文帅     董嘉豪     黄…

第五届湖南省机器人大赛暨第十四届湖南省智能汽车大赛名单

简 介&#xff1a; 本文汇总了第五届湖南省智能车竞赛的基本信息。感谢中南大学王击老师发送过来的信息。 关键词&#xff1a; 湖南省智能车竞赛&#xff0c;智能车竞赛 #mermaid-svg-Bl4gxd2xsRwJqsTI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-s…

第十七届全国大学生智能车竞赛线上比赛直播链接

01 直播信息 惠州学院赛点比赛时间安排表以及直播链接 7月25日上午组别学校&队伍名称时间直播B站直播链接 四轮电磁东江-白夜&#xff08;惠州学院&#xff09;9:00-9:20直播1https: b23.tv FnIhJ5g 腾讯会议&#xff1a;976-769-477 四轮摄像头一路顺风&#xff08;东软…

SCAU操作系统知识点之(五)并发:互斥和同步

1、互斥的概念 互斥&#xff1a;当一个进程在临界区访问共享资源时&#xff0c;其他进程不能进入该临界区访问任何共享资源。 用硬件实现进程互斥时&#xff0c;中断禁用适于单 CPU 系统&#xff0c;多 CPU 系统可使用专用机器指令。 2、临界资源与临界区 临界区&#xff1a;一…

iOS 组件化的三种方案

组件化 本文主要介绍iOS组件化的三种方案 1、常⽤的三种方案 URL SchemeTarget - ActionProtocol - Class 匹配 1.1、 URL Scheme路由 使 URL 处理本地的跳转通过中间层进⾏注册 & 调⽤ &#xff08;load方法里把被调用者注册到中间层&#xff09;注册表⽆需使用反射非…

《最强大模型平台上线,被很多行业“盯”上了》

千帆大模型 1、国内最多的模型2、国内最全的Prompt模板3、总结 千帆大模型平台是面向企业开发者的一站式大模型开发及服务运行平台&#xff0c;也是百度智能云推出的全球首个一站式企业级大模型平台。在提供全套文心大模型服务的基础上&#xff0c;还支持第三方开源大模型、各种…

【2020年底攻略】支付宝沾沾卡怎么获得 沾沾卡获取攻略分享

沾福气卡是支付宝中的一个特殊卡片&#xff0c;用这个新卡有机会复制朋友的任何一张卡牌&#xff0c;很多玩家不知道如何获取这张卡&#xff0c;下面来为大家带来的介绍。 沾福气卡怎么获得 1月28日-2月4日18点期间&#xff0c;每日手臂付款可以领取一张沾福气卡&#xff1b;…

2021支付宝集五福【攻略】!!!

一年一度的支付宝集五福在2月1号的凌晨开始了&#xff0c;虽然一年比一年瓜分的少&#xff0c;但不知不觉集福卡成了过年最佳的消遣娱乐方式了。活动从2月1日开始至1月11日结束。 零、额外福利 额外福卡二维码扫福器下载地址&#xff1a;https://syx0226.lanzous.com/iOP2Zl5w…

随机送一张花花卡跟一张敬业卡

马云的福字火了&#xff0c;猪肉铺大叔你也火了……马云福字是什么梗&#xff1f;之前马云曾写过一个福字&#xff0c;福中有田有猪有网有支付宝&#xff0c;昨天&#xff0c;有网友表示&#xff0c;一位菜市场的猪肉老板大叔对这个福字很中意&#xff0c;在店铺前挂出了这个福…

分割一切模型 Fast SAM C++推理部署---onnxruntime(有核心代码)

Fast SAM C推理部署—onnxruntime 核心源代码在结尾处 晓理紫 0 XX开局一张图&#xff0c;剩下… 本文记录只为日后更好学习 1 Fast SAM 简介 Fast SAM是仅使用SAM作者发布的SA-1B数据集的2%进行训练的CNN任意分割模型。FastSAM的性能与SAM方法相当&#xff0c;运行速度提高了…

支付宝五福53张自动领取程序 v2021

简介&#xff1a; 临近过年&#xff0c;身边的朋友们都开始参加支付宝一年一度的集五福活动了&#xff01;今天小编带来的这款支付宝五福53张自动领取程序能够帮助集福的朋友们更加轻松地完成任务&#xff0c;让用户一键完成53个任务并自动获取福卡&#xff0c;非常方便&#…

2920集五福_2020年支付宝集五福攻略

支付宝2020扫福活动在今天也就是1月13日开始啦&#xff0c;听说&#xff0c;居然有2.4万人集齐了吗&#xff0c;也太快了吧&#xff01;有人好奇&#xff0c;2020年支付宝集五福活动规则&#xff0c;有什么新玩法。不过不少小伙伴们比较关心的是2020每天可以扫几张福&#xff1…

2020 春节集五福最详细收集攻略

本文由葡萄城技术团队于博客原创并首发 转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 一年一度的支付宝集五福活动已经开始了&#xff0c;不知从什么时候开始&#xff0c;集五福已经成为了惯例…

已有一万名快手用户集齐好运卡获得六六六早鸟红包,还可再分一亿

“谁要来沾幸运的吗&#xff01;我已经集齐了&#xff01;“ “天呐&#xff0c;马上就要到一万人&#xff01;谁能让我沾一沾幸运&#xff01;“ 伴随着超话里网友们热火朝天的讨论&#xff0c;快手「集好运中国福」活动也终于迎来了第1万个集齐五张好运卡的幸运用户。 据了…