当前位置: 首页 > news >正文

【C++模板进阶】

目录

  • 一、模板使用时的一个小注意点
  • 二、非类型模板参数
  • 三、类模板的特化
    • 3.1函数模板的特化
    • 3.2类模板的特化
      • 3.2.1全特化
      • 3.2.2偏特化
  • 四、模板的分离编译
    • 4.1模板不支持分离编译
    • 4.2模板分离编译报错的分析
    • 4.2解决方案
  • 五、模板的总结

一、模板使用时的一个小注意点

在使用模板时,在有些场景下需要加上typename来告诉编译器这里是类型,否则会编译不通过。如:我想写一个不只是针对vector类型打印数据该怎么改写上面的代码呢?

#include<iostream>
using namespace std;#include<vector>void Print(const vector<int>& v)
{vector<int>::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";}cout<<endl;
}
int main()
{vector<int> v;v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);v.push_back(50);Print(v);return 0;
}

首先对于泛型编程的思想一般都会考虑到用模板,所以一般我们都会这么改写代码。如:

#include<iostream>
using namespace std;#include<vector>
template<class Container>
void Print(const Container& v)
{Container::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout<<endl;
}
int main()
{vector<int> v;v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);v.push_back(50);Print(v);return 0;
}

但是呢这种代码连编译都通过不了。如:
在这里插入图片描述
为什呢?
其实是编译器不知道Container::const_iterator这个是类型还是对象
需要在前面加上typename告诉编译器这个是类型,等模板实例化后再去找。如:
在这里插入图片描述

二、非类型模板参数

假设有这样一个场景,我需要创建2个静态的顺序表。一个顺序表的容量是10个,另一个是1000个,该怎么玩呢?按照常规的方法肯定是玩不了的,这时就需要非类型模板参数了。可以这么玩。如:

namespace Ting
{template<class T,size_t N>class vector{private:T _arr[N];size_t capapcity;};
}int main()
{Ting::vector<int, 10> v1;Ting::vector<int, 1000> v2;return 0;
}

在这里插入图片描述
注意:

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  2. 非类型的模板参数必须在编译期就能确认结果且不能被修改。

三、类模板的特化

3.1函数模板的特化

直接先看代码,见一见猪跑。

//函数模板的特化
template<class T>
bool Less(T x, T y)
{return x < y;
}//对函数模板进行特化
template<>
bool Less<int*>(int* x, int* y)
{return *x < *y;
}
int main()
{int a = 2, b = 1;cout << Less(&a, &b) << endl;return 0;
}

乍一看是不是感觉函数模板特化有点与函数重载类似?感觉这个没啥用,但是这个是错觉。如:

//函数模板的特化
template<class T>
bool Less(T x, T y)
{return x < y;
}//对函数模板进行特化
template<class T>
bool Less(T* x, T* y)
{return *x < *y;
}
int main()
{int a = 2, b = 1;double c = 2.1, d = 2.2;cout << Less(&a, &b) << endl;cout << Less(&c, &d) << endl;return 0;
}

这种写法比函数重载要方便多了。
函数模板的特化步骤:

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

3.2类模板的特化

类模板的特化的步骤:
1.必须要有基础的类模板
2.关键字template后面接一对空的尖括号<>
3.类名后跟一对尖括号<>,尖括号中指定需要特化的类型。
类模板的特化分为:全特化和偏特化

3.2.1全特化

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

//函数模板的全特化
template<class T1,class T2>
class Ting
{
public:Ting(){cout << "Ting<T1,T2>" << endl;}
};
template<>
class Ting<int,char>
{
public:Ting(){cout << "Ting<int,char>" << endl;}
};
template<>
class Ting<double, char>
{
public:Ting(){cout << "Ting<double,char>" << endl;}
};int main()
{Ting<int, float> zft01;Ting<double, char> zft02;Ting<int, char> zft03;Ting<float, int> zft04;return 0;
}

3.2.2偏特化

//函数模板的偏特化
template<class T1, class T2>
class Ting
{
public:Ting(){cout << "Ting<T1,T2>" << endl;}
};template<class T1>
class Ting<T1,int>
{
public:Ting(){cout << "Ting<T1,int>" << endl;}
};template<class T1>
class Ting<T1, double>
{
public:Ting(){cout << "Ting<T1,double>" << endl;}
};//还可以对某种类型参数做进一步限制 如:
template<class T1,class T2>
class Ting<T1*,T2*>
{
public:Ting(){cout << "Ting<T1*,T2*>" << endl;}
};template<class T1, class T2>
class Ting<T1&, T2&>
{
public:Ting(){cout << "Ting<T1&,T2&>" << endl;}
};int main()
{return 0;
}

四、模板的分离编译

4.1模板不支持分离编译

比如有这样一个Add函数。如:
.h文件

#pragma once
template<class T>
T Add(T x, T y);

.cpp文件

#include"Add.h"template<class T>
T Add(T x, T y)
{return x + y;
}

测试文件

//模板的分离编译
#include"Add.h"
int main()
{cout << Add(1, 2) << endl;return 0;
}

运行时就会出现这样的报错。如:在这里插入图片描述

4.2模板分离编译报错的分析

为什么会这样呢?
分析:
C/C++程序要运行,一般要经历一下步骤:
预处理—>编译—>汇编—>链接

编译:对程序按照语言特性进行词法、语法、语义分析,错误检查无误后生成汇编代码。注意头文件不参与编译,编译器对工程中的多个源文件是分离开单独编译的。
链接:将多个obj文件合成一个,并处理没有解决的地址问题。
在这里插入图片描述

4.2解决方案

第一种方法:显示实例化
.cpp文件

#include"Add.h"template<class T>
T Add(T x, T y)
{return x + y;
}//显示实例化
template
int Add(int x,int y);
int Add(double x, double y);

(以上的方法不推荐)
第二种方法:将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。

五、模板的总结

【优点】

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性
    【缺陷】
  3. 模板会导致代码膨胀问题,也会导致编译时间变长
  4. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

相关文章:

【C++模板进阶】

目录 一、模板使用时的一个小注意点二、非类型模板参数三、类模板的特化3.1函数模板的特化3.2类模板的特化3.2.1全特化3.2.2偏特化 四、模板的分离编译4.1模板不支持分离编译4.2模板分离编译报错的分析4.2解决方案 五、模板的总结 一、模板使用时的一个小注意点 在使用模板时&…...

(一)RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理

Lison <dreamlison163.com>, v1.0.0, 2023.06.22 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理 文章目录 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理RabbitMQ概念RabbitMQ的优势RabbitMQ劣势RabbitMQ应用的场景RabbitMQ_AMQPRabbitMQ工作原理 RabbitM…...

JetBrains全家桶:如何自定义实现类TODO注释?

文章目录 效果图具体方法参考文献 效果图 TODO注释大家应该都用过&#xff0c;在注释开头打上TODO的话&#xff0c;软件下方的TODO选项卡里就可以自动筛选出你打了TODO的注释&#xff0c;你可以点击里面对应的注释来实现快速跳转。 jetbrains全家桶&#xff08;如Pycharm、Int…...

【技术干货】工业级BLE5.2蓝牙模块SKB378 使用教程,AT指令集

SKB378是一个高度集成的蓝牙5.2模组&#xff0c;可用来在2.4GHz ISM频段内做高速率、短距离无线通信。工业级标准&#xff0c;支持主从模式(1主对8从)&#xff0c;支持串口透传&#xff0c;AT指令控制&#xff0c;且支持AoA蓝牙高精度室内定位&#xff0c;模组内部集成32位ARM …...

零基础深度学习——学习笔记1 (逻辑回归)

前言 因为各种各样的原因要开始学习深度学习了&#xff0c;跟着吴恩达老师的深度学习视频&#xff0c;自己总结一些知识点&#xff0c;以及学习中遇到的一些问题&#xff0c;以便记录学习轨迹以及以后复习使用&#xff0c;为了便于自己理解&#xff0c;我会将一些知识点用以个…...

I want to know on what switchport is connected my computer (10.8.0.2)

i.e. I am connected to an L2. I want to know on what switchport is connected my computer (10.8.0.2) Well….obviously not on this switch. Let’s dig Now I have the MAC address of my computer, we confinue to dig Computer has been seen on interface g0/2. Let’…...

OpenCv之人脸操作

目录 一、马赛克实现 二、人脸马赛克 三、人脸检测 四、多张人脸检测 一、马赛克实现 案例代码如下: import cv2 import numpy as npimg cv2.imread(8.jpg) # 马赛克方式一:缩小图片 # img2 cv2.resize(img,(600,400)) # # 马赛克方式二: # img2 cv2.resize(img,(600,4…...

C++[第五章]--指针和引用

指针和引用 文章目录 指针和引用1、引用2、指针3、右值引用4、引用限定符const和引用限定符1、引用 引用就是别名,引用定义时必须初始化: int a; int &b=a; //b即为a的别名 如果不是形参,必须初始化,引用某一变量 2、指针 指针和c一样; this指针 在类的成员函数中使…...

用i18next使你的应用国际化-React

ref: https://www.i18next.com/ i18next是一个用JavaScript编写的国际化框架。 i18next为您提供了一个完整的解决方案&#xff0c;本地化您的产品从web端到移动端和桌面端。 在react项目中安i18next依赖&#xff1a; i18nextreact-i18nexti18next-browser-languagedetector&…...

TSN -促进IT/OT 融合的网络技术

时间敏感网络&#xff08;tsn&#xff09;技术是IT/OT 融合的一项关键的基础网络技术&#xff0c;它实现了在一个异构网络中&#xff0c;实现OT的实时数据和IT系统的交互数据的带宽共享。 TSN允许将经典的高确定性现场总线系统和IT应用&#xff08;如大数据传输&#xff09;的功…...

改进的北方苍鹰算法优化BP神经网络---回归+分类两种案例

今天采用前作者自行改进的一个算法---融合正余弦和折射反向学习的北方苍鹰(SCNGO)优化算法优化BP神经网络。 文章一次性讲解两种案例&#xff0c;回归与分类。回归案例中&#xff0c;作者选用了一个经典的股票数据。分类案例中&#xff0c;选用的是公用的UCI数据集。 BP神经网络…...

等保工作如何和企业创新业务发展相结合,实现“安全”和“创新”的火花碰撞?

等保工作如何和企业创新业务发展相结合&#xff0c;实现“安全”和“创新”的火花碰撞&#xff1f;在当今数字化浪潮的背景下&#xff0c;企业越来越需要在“安全”和“创新”之间找到平衡点&#xff0c;以实现业务的持续创新和安全的有效保障。等保工作可以为企业提供安全保障…...

23.7.25 杭电暑期多校3部分题解

1005 - Out of Control 题目大意 解题思路 code 1009 - Operation Hope 题意、思路待补 code #include <bits/stdc.h> using namespace std; const int N 1e5 9; struct lol {int x, id;} e[3][N * 2]; int t, n, a[3][N * 2], hd[3], tl[3], vis[N * 2], q[N * …...

【设计模式——学习笔记】23种设计模式——桥接模式Bridge(原理讲解+应用场景介绍+案例介绍+Java代码实现)

问题引入 现在对不同手机类型的不同品牌实现操作编程(比如:开机、关机、上网&#xff0c;打电话等)&#xff0c;如图 【对应类图】 【分析】 扩展性问题(类爆炸)&#xff0c;如果我们再增加手机的样式(旋转式)&#xff0c;就需要增加各个品牌手机的类&#xff0c;同样如果我们…...

文档翻译软件那么多,哪个能满足你的多语言需求?

想象一下&#xff0c;你手中拿着一份外文文件&#xff0c;上面记录着珍贵的知识和信息&#xff0c;但是语言的障碍让你无法领略其中的内容。而此时&#xff0c;一位翻译大师闪亮登场&#xff01;他的翻译技巧犹如一把魔法笔&#xff0c;能够将文字的魅力和意境完美传递。无论是…...

MySQL 中NULL和空值的区别

MySQL 中NULL和空值的区别&#xff1f; 简介NULL也就是在字段中存储NULL值&#xff0c;空值也就是字段中存储空字符(’’)。区别 1、空值不占空间&#xff0c;NULL值占空间。当字段不为NULL时&#xff0c;也可以插入空值。 2、当使用 IS NOT NULL 或者 IS NULL 时&#xff0…...

阿里云容器镜像仓库(ACR)的创建和使用

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

工业的相机与镜头(简单选型)

面阵相机&#xff0c;需要多大的分辨率&#xff1f;多少帧数&#xff1f; 前提条件&#xff1a; 1.被检测的物体大小 2.要求检测的精度是多少 3.物体是否在运动过程中进行检测&#xff0c;速度是多少 线阵相机选择(分辨率、扫描行数) 行频&#xff1a;每秒扫描多少行&#xf…...

numpy广播机制介绍

广播 广播机制的意义&#xff1a;广播描述了在算术运算期间NumPy如何处理具有不同形状的数组。受某些约束条件的限制&#xff0c;较小的数组会在较大的数组中“广播”&#xff0c;以便它们具有兼容的形状。 在对两个数组进行操作时&#xff0c;NumPy按元素对它们的形状进行比…...

RocketMQ 5.0 无状态实时性消费详解

作者&#xff1a;绍舒 背景 RocketMQ 5.0 版本引入了 Proxy 模块、无状态 pop 消费机制和 gRPC 协议等创新功能&#xff0c;同时还推出了一种全新的客户端类型&#xff1a;SimpleConsumer。 SimpleConsumer 客户端采用了无状态的 pop 机制&#xff0c;彻底解决了在客户端发布…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”

非常好&#xff0c;我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题&#xff0c;统一使用 二重复合函数&#xff1a; z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y))​ 来全面说明。我们会展示其全微分形式&#xff08;偏导…...

Linux基础开发工具——vim工具

文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...

StarRocks 全面向量化执行引擎深度解析

StarRocks 全面向量化执行引擎深度解析 StarRocks 的向量化执行引擎是其高性能的核心设计&#xff0c;相比传统行式处理引擎&#xff08;如MySQL&#xff09;&#xff0c;性能可提升 5-10倍。以下是分层拆解&#xff1a; 1. 向量化 vs 传统行式处理 维度行式处理向量化处理数…...