C++模板知识

目录

引言 

一、非类型模板参数

二、类模板的特化 

(一)概念 

(二)函数模板特化 

(三)类模板特化 

1. 全特化 

2. 偏特化 

(四)类模板特化应用示例 

三、模板的分离编译 

(一)什么是分离编译 

(二)模板的分离编译 

(三)解决方法 

四、模板总结 

(一)优点 

(二)缺陷 


引言

在C++编程世界里,模板是一项极为强大且灵活的特性,它能让我们编写出通用、可复用的代码。今天,就让我们深入探究C++模板的几个关键方面:非类型模板参数、类模板的特化以及模板的分离编译。
 

一、非类型模板参数

模板参数分为类型形参与非类型形参。类型形参,我们常见于模板参数列表中,通常紧跟在 class 或者 typename 之后。而非类型模板参数则别具一格,它使用一个常量作为类(函数)模板的一个参数,在模板中可当作常量使用。
 
代码示例
 

cpp   
namespace bite {// 定义一个模板类型的静态数组template<class T, size_t N = 10>class array {public:T& operator[](size_t index) { return _array[index]; }const T& operator[](size_t index) const { return _array[index]; }size_t size() const { return _size; }bool empty() const { return 0 == _size; }private:T _array[N];size_t _size;};
}


 注意事项
 
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的,用整形初始化
 
2. 非类型的模板参数必须在编译期就能确认结果。
 

二、类模板的特化
 

(一)概念
 

模板能实现与类型无关的代码,但遇到特殊类型时,可能会产生错误结果,这就需要对模板进行特化。特化即在原模板类基础上,针对特殊类型进行特殊化的实现方式。模板特化主要分为函数模板特化与类模板特化。
 

(二)函数模板特化
 

特化步骤
 
1. 首先得有一个基础的函数模板。
 
2. 使用关键字 template 后跟一对空的尖括号 <> 。
 
3. 函数名后紧跟一对尖括号,在尖括号中指定需要特化的类型。
 
4. 函数形参表必须要和模板函数的基础参数类型完全相同,否则不同编译器可能会报奇怪错误。


代码示例
 

cpp   
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right) {return left < right;
}// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* 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. 全特化
 

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

cpp   
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 _d2;
};


 

2. 偏特化
 

偏特化是针对模板参数进一步进行条件限制设计的特化版本,主要有以下两种表现方式:
 
- 部分特化:将模板参数类表中的一部分参数特化。
 

cpp   
// 将第二个参数特化为int
template <class T1>
class Data<T1, int> {
public:Data() { cout << "Data<T1, int>" << endl; }
private:T1 _d1;int _d2;
};


 
 
- 参数更进一步的限制:不仅特化部分参数,还针对模板参数做更进一步的条件限制。
 

cpp   
// 两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data<T1*, T2*> {
public:Data() { cout << "Data<T1*, T2*>" << endl; }
private:T1* _d1;T2* _d2;
};// 两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data<T1&, T2&> {
public:Data(const T1& d1, const T2& d2) : _d1(d1), _d2(d2) {cout << "Data<T1&, T2&>" << endl;}
private:const T1& _d1;const T2& _d2;
};


 

(四)类模板特化应用示例
 


以按照小于比较的类模板 Less 为例:
 

cpp   
#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);// 此处直接排序结果错误,因为sort最终按照Less模板中方式比较,只会比较指针,而非指针指向内容// 此时需要特化Less类模板来处理sort(v2.begin(), v2.end(), Less<Date*>());return 0;
}// 对Less类模板按照指针方式特化
template<>
struct Less<Date*> {bool operator()(Date* x, Date* y) const {return *x < *y;}
};


 

三、模板的分离编译
 

(一)什么是分离编译
 


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


(二)模板的分离编译
 


当模板的声明与定义分离开,在头文件中声明,源文件中定义时,会出现问题。例如:
a.h
 

cpp   
template<class T>
T Add(const T& left, const T& right);a.cppcpp   
template<class T>
T Add(const T& left, const T& right) {return left + right;
}main.cppcpp   
#include "a.h"
int main() {Add(1, 2);Add(1.0, 2.0);return 0;
}


 
在这种情况下, a.cpp 中编译器没看到对 Add 模板函数的实例化,不会生成具体的加法函数; main.cpp 编译后在链接时找不到 Add<int> 与 Add<double> 的具体代码,就会报错。
 

(三)解决方法
 


1. 将声明和定义放到一个文件“xxx.hpp”里或者 xxx.h 也可以,推荐这种方式。
 
2. 模板定义的位置显式实例化,但这种方法不实用,不推荐。

 

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


四、模板总结
 

(一)优点
 


1. 模板复用了代码,节省资源,能实现更快的迭代开发,C++的标准模板库(STL)就是基于模板产生的。
 
2. 增强了代码的灵活性,能适应多种数据类型。
 


(二)缺陷
 

1. 模板会导致代码膨胀问题,编译时会针对不同类型实例化出多份代码,也会使编译时间变长。
 
2. 出现模板编译错误时,错误信息非常凌乱,难以定位错误根源。
 
希望通过这篇博客,大家能对C++模板有更深入、全面的理解,在今后的编程中能更好地运用模板特性编写出高质量、可复用的代码。

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

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

相关文章

Pillow 移除或更改了 FreeTypeFont.getsize() 方法

w, h self.font.getsize(label) # text width, height AttributeError: FreeTypeFont object has no attribute getsize 在Pillow 项目的变更日志里可以查到哪个版本移除了 getsize() 方法&#xff0c;Pillow仓库&#xff1a; Releases python-pillow/Pillow GitHub 因为…

Matlab自学笔记

一、我下载的是Matlab R2016a软件&#xff0c;打开界面如下&#xff1a; 二、如何调整字体大小&#xff0c;路径为&#xff1a;“主页”->“预设”->“字体”。 三、命令行窗口是直接进行交互式的&#xff0c;如下输入“3 5”&#xff0c;回车&#xff0c;就得到结果“…

VR汽车线束:汽车制造的新变革

汽车线束&#xff0c;作为汽车电路网络的主体&#xff0c;宛如汽车的 “神经网络”&#xff0c;承担着连接汽车各个部件、传输电力与信号的重任&#xff0c;对汽车的正常运行起着关键作用。从汽车的发动机到仪表盘&#xff0c;从传感器到各类电子设备&#xff0c;无一不是通过线…

目标检测YOLO实战应用案例100讲-基于多级特征融合的小目标深度检测网络

目录 知识储备 基于多级特征融合的小目标深度检测网络实现 一、环境配置 二、核心代码实现 1. 多级特征融合模块(models/fpn.py ) 2. 主干网络(models/backbone.py ) 3. 检测头(models/detector.py ) 三、完整网络架构(models/net.py ) 四、训练代码(train.p…

【云原生】基于Centos7 搭建Redis 6.2 操作实战详解

目录 一、前言 二、Redis 6.2 安装过程 2.1 下载安装包 2.2 安装包解压 2.3 安装包编译 2.3 安装 2.4 启动redis 2.4.1 前台启动&#xff08;不推荐&#xff09; 2.4.2 后启动&#xff08;推荐&#xff09; 2.4.3 关闭redis服务 2.4.4 设置客户端连接 三、写在最后 …

云计算-容器云-服务网格

服务网格:创建VirtualService(3分) ​ 将Bookinfo应用部署到default命名空间下,为Bookinfo应用创建一个名为reviews的VirtualService,要求来自名为Jason的用户的所有流量将被路由到reviews服务的v2版本。(需要用到的软件包:ServiceMesh.tar.gz) # 上传解压 tar -xf Se…

【Res模块学习】结合CIFAR-100分类任务学习

初次尝试训练CIFAR-100&#xff1a;【图像分类】CIFAR-100图像分类任务-CSDN博客 1.训练模型&#xff08;MyModel.py&#xff09; import torch import torch.nn as nnclass BasicRes(nn.Module):def __init__(self, in_cha, out_cha, stride1, resTrue):super(BasicRes, sel…

爱胜品ICSP YPS-1133DN Plus黑白激光打印机报“自动进纸盒进纸失败”处理方法之一

故障现象如下图提示&#xff1a; 用户的爱胜品ICSP YPS-1133DN Plus黑白激光打印机在工作过程中提示自动进纸盒进纸失败并且红色故障灯闪烁&#xff1b; 给出常见故障一般处理建议如下&#xff1a; 当您的爱胜品ICSP YPS-1133DN Plus 黑白激光打印机出现“自动进纸盒进纸失败”…

Flinkcdc 实现 MySQL 写入 Doris

Flinkcdc 实现 MySQL 写入 Doris Flinkcdc 实现 MySQL 写入 Doris 一、环境配置 Doris&#xff1a;3.0.4 JDK 17 MySQL &#xff08;业务数据库&#xff09;&#xff1a;5.7 MySQL&#xff08;本地数据库&#xff09;&#xff1a;5.7 Flink&#xff1a;flink-1.19.1 flinkc…

【Linux庖丁解牛】—环境变量!

目录 1. 环境变量 1.1 概念介绍 1.2 命令行参数 1.3 一个例子&#xff0c;一个环境变量 1.4 认识更多的环境变量 1.5 获取环境变量的方法 a. 指令操作 b. 代码操作 1.6 理解环境变量的特性 a.环境变量具有全局特性 b.补充两个概念(为后面埋一个伏笔) 1. 环境变量 …

LangChain4j +DeepSeek大模型应用开发——7 项目实战 创建硅谷小鹿

这部分我们实现硅谷小鹿的基本聊天功能&#xff0c;包含聊天记忆、聊天记忆持久化、提示词 1. 创建硅谷小鹿 创建XiaoLuAgent package com.ai.langchain4j.assistant;import dev.langchain4j.service.*; import dev.langchain4j.service.spring.AiService;import static dev…

普通 html 项目也可以支持 scss_sass

项目结构示例 下载vscode的插件Live Sass Compiler 自动监听编译scss 下载插件Live Server 用于 web 服务器&#xff0c;打开 html 文件到浏览器&#xff0c;也可以不用这个&#xff0c;自己用 nginx 或者宝塔其他 web 工具 新建一个 index.scss打开&#xff0c;点击 vscode 底…

网工_IP协议

2025.02.17&#xff1a;小猿网&网工老姜学习笔记 第19节 IP协议 9.1 IP数据包的格式&#xff08;首部数据部分&#xff09;9.1.1 IP协议的首部格式&#xff08;固定部分可变部分&#xff09; 9.2 IP数据包分片&#xff08;找题练&#xff09;9.3 TTL生存时间的应用9.4 常见…

SQL语句练习 自学SQL网 在查询中使用表达式 统计

目录 Day 9 在查询中使用表达式 Day 10 在查询中进行统计 聚合函数 Day 11 在查询中进行统计 HAVING关键字 Day12 查询执行顺序 Day 9 在查询中使用表达式 SELECT id , Title , (International_salesDomestic_sales)/1000000 AS International_sales FROM moviesLEFT JOIN …

基于机器学习的舆情分析算法研究

标题:基于机器学习的舆情分析算法研究 内容:1.摘要 随着互联网的飞速发展&#xff0c;舆情信息呈现爆炸式增长&#xff0c;如何快速准确地分析舆情成为重要课题。本文旨在研究基于机器学习的舆情分析算法&#xff0c;以提高舆情分析的效率和准确性。方法上&#xff0c;收集了近…

菲索旋转齿轮法:首次地面光速测量的科学魔术

一、当齿轮邂逅光束&#xff1a;19世纪的光速实验室 1849年&#xff0c;法国物理学家阿曼德菲索&#xff08;Armand Fizeau&#xff09;在巴黎郊外的一座庄园里&#xff0c;用一组旋转齿轮、一面镜子和一盏油灯&#xff0c;完成了人类首次地面光速测量。他的实验测得光速为315…

上位机知识篇---PSRAM和RAM

文章目录 前言一、RAM&#xff08;Random Access Memory&#xff09;1. 核心定义分类&#xff1a;SRAM&#xff08;静态RAM&#xff09;DRAM&#xff08;动态RAM&#xff09; 2. 关键特性SRAM优点缺点应用 DRAM优点缺点应用 3. 技术演进DDR SDRAMLPDDR&#xff08;低功耗DRAM&a…

Qt QComboBox 下拉复选多选(multicombobox)

Qt QComboBox 下拉复选多选&#xff08;multicombobox&#xff09;&#xff0c;备忘&#xff0c;待更多测试 【免费】QtQComboBox下拉复选多选&#xff08;multicombobox&#xff09;资源-CSDN文库

ElasticSearch深入解析(五):如何将一台电脑上的Elasticsearch服务迁移到另一台电脑上

文章目录 0.安装数据迁移工具1.导出数据2.导出mapping3.导出查询模板4.拷贝插件5.拷贝配置6.导入到目标电脑上 0.安装数据迁移工具 Elasticsearch dump是一个用于将Elasticsearch索引数据导出为JSON格式的工具。你可以使用Elasticsearch dump通过命令行或编程接口来导出数据。…

微服务中组件扫描(ComponentScan)的工作原理

微服务中组件扫描(ComponentScan)的工作原理 你的问题涉及到Spring框架中ComponentScan的工作原理以及Maven依赖管理的影响。我来解释为什么能够扫描到common模块的bean而扫描不到其他模块的bean。 根本原因 关键在于**类路径(Classpath)**的包含情况&#xff1a; Maven依赖…