把值写进类型:C++ 模板进阶的非类型参数、特化与分离编译
浮世尘弦个人主页⭐个人专栏《C语言》、《数据结构与算法》、《C》非淡薄无以明志非宁静无以致远前言前面我们学习了使用类型模板参数templateclass T编写与类型无关的通用代码但是对于 泛型编程来说光有类型模板参数是不够的。本篇文章就要再次基础上再次增加非类型模板参数模板特化模板的分离编译等内容。帮助你深入理解和上手泛型编程。让我开始今天的学习吧文章目录一非类型模版参数1介绍非类型模版参数2array数组二模版特化1函数模板特化​编辑2全特化和偏特化三模板分离编译1,介绍分离编译2模板的声明和定义为什么不能分离四函数模板的优缺点一非类型模版参数在之前我们学习了类型模版参数templateclass TT可以替代任意类型但是不能替代一个实际的常数在一些场景下我们需要用一个常数来定义容器的容量。于是就引入了非类型模版参数。故模版参数分为类型形参和非类型形参。类型形参在之前的已经讲解过具体可以看我的这一篇文章C 核心进阶一泛型编程基石 —— 模板初阶与 STL 体系开篇接下来我们详细讲解一下非类型参数1介绍非类型模版参数非类型参数用一个常数作为类(函数)模版的参数在类函数模版中可以当成一个常量进行使用。本质上是一个编译期常量值。C17只支持整形int/short/size_t/bool 指针 auto不支持浮点数类类型字符串在C20之后才支持了浮点数类类型使用展示//#define N 10//这里使用宏定义N的值不能进行修改 //这里使用非类型模版参数N可以进行修改 template size_t N 10//可以使用缺省值 class arr { private: int arr[N]; int top; }; int main() { arr3 a1;//中的数字就是自定义的容量N arr6 a2; arr a3;//使用缺省值 return 0; }2array数组cplusplus文档array文档array是一个静态数组使用的是随机迭代器迭代器为原生指针。需要包含头文件#include array下面是使用的案例主要包括越界检查template class T,size_t N 20 class Myarray { public: T operator[](size_t index) { assert(index N);//底层检查越界 return arr[index]; } private: T arr[N]; size_t size; }; int main() { //array是一个静态数组使用的是随机迭代器原生指针 arrayint, 10 a1; //类似于下面的静态数组 int arr[10]; //这两者有一个核心的区别越界的检查 //上面的静态数组arr 在读时不进行检查 //cout arr[10] endl;//arr[10]在底层就是一个指针解引用 //在写时进行抽查就是检查arr数组的后两个位置的值是否被修改 //arr[10] 11; //arr[11] 12; //arr[20] 23; //array越界的读和写都会被检查出来 //原因是他调用的是函数,调用的函数类似于上面的Myarray //a1[11]; //a1[13] 13; vectorint v2(10, 100); //vector在堆上开辟,Debug下会在3个指针的基础上加上一个代理指针 //release下就是三个指针 cout sizeof(v2) endl;//Debug下32release下24 //array静态在栈上开辟大小需要看开辟了多少空间 cout sizeof(a1) endl;//40 //栈上管理内存比堆上容易 return 0; }静态数组arr下的抽查二模版特化⭐1函数模板特化我们先来看一组案例日期类内含日期的比较逻辑//日期类 class Date { friend ostream operator(ostream _cout, const Date d); public: Date(int year 1900, int month 1, int day 1) : _year(year) , _month(month) , _day(day) {} bool operator(const Date d)const { return (_year d._year) || (_year d._year _month d._month) || (_year d._year _month d._month _day d._day); } bool operator(const Date d)const { return (_year d._year) || (_year d._year _month d._month) || (_year d._year _month d._month _day d._day); } private: int _year; int _month; int _day; };//函数模版 template class T bool LessFunc(const T a1, const T a2) { return a1 a2; } int main() { cout LessFunc(1, 2) endl;//结果正确1 Date d1(2015, 3, 4); Date d2(2018, 5, 13); cout LessFunc(d1, d2) endl;//结果正确1 Date* p1 d2; Date* p2 d1; //由于比较的是地址而地址是随机分配的导致结果错误 cout LessFunc(p1, p2) endl;//结果错误1 const Date* p3 d2; const Date* p4 d1; cout LessFunc(p3, p4) endl;//结果错误1 return 0; }上面的模版不能支持下面两种特殊情况这时候就需要进行特化//函数模版 template class T bool LessFunc(const T a1, const T a2) { return a1 a2; } //函数特化 //Date* 和 const Date*类型的参数用下面的 template bool LessFuncDate*(Date* const a1, Date* const a2) { return *a1 *a2; } template bool LessFuncconst Date*(const Date* const a1, const Date* const a2) { return *a1 *a2; }此时加上下面的两个特化后结果就是正确的由此引出模版特化的概念在原模版的基础上针对特殊类型进行特殊化的实现方式。模版特化不只有上面的函数特化一种类型还有类模版特化。函数模板特化的步骤1必须要有一个基础的模板才能进行特化2关键字template后面要加上3函数名后面要加上面特化的类型。4函数模板特化的参数必须要和基础模板的参数类型完全相同。2全特化和偏特化模板的特化分为两种全特化将模板列表中的参数全部确定化。偏特化只指定一部分参数进行特化或者对参数加上特定模式的限制例如限制为指针引用相同类型template class T1,class T2 class Data { public: Data() { cout DataT1,T2 endl; } private: T1 d1; T2 d2; }; //类模板-全特化 template class Dataint, double { public: Data() { cout Dataint,double endl; } }; //偏特化 templateclass T1 class DataT1,double { public: Data() { cout Dataclass T1,double endl; } }; int main() { Dataint, char d1; Dataint, double d2; Datadouble, double d3; return 0; }运行展示特化会优先走实例化少的例如Dataint,double就不会走Dataclass T1,double偏特化指针与引用templateclass T1,class T2 class DataT1*, T2* { public: Data() { cout DataT1*,T2* endl; } }; templateclass T1,class T2 class DataT1, T2 { public: Data() { cout DataT1T2 endl; } }; templateclass T1,class T2 class DataT1*, T2 { public: Data() { cout DataT1*,T2 endl; } }; int main() { //Dataint, char d1; //Dataint, double d2; //Datadouble, double d3; Datachar*, double* d4; Datachar, double d6; Datachar*, double d7; return 0; }运行结果特殊内容补充三模板分离编译1,介绍分离编译一个程序项目由若干个源文件共同实现每个源文件单独编译生成目标文件最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。一个C/C程序要运行下去一般要经历这几个过程详细内容可以看下面两期博客详解预处理编译与链接2模板的声明和定义为什么不能分离上面的Func是一个普通函数函数声明放在.h文件当中定义放在Func.cpp当中当在最后一步时将文件和并到一起时进行实例化可以直接找到函数的地址。而Add模板函数由于没有确定类型T导致不能进行实例化。没有进行实例化导致在链接时找不到函数的地址无法完成链接。解决方法1将函数模板的声明和定义放到同一个文件当中。2模板定义位置显式实例化不推荐四函数模板的优缺点⭐优点1,极高的代码复用性可以直接省去写类似逻辑的重载函数2. 编译期的类型安全相比于 C 语言中的宏#define MAX(a,b) ...或void*函数模板是类型安全的。宏只是简单的文本替换没有类型检查容易产生副作用。模板在编译期推导类型如果你传入不支持比较的类型编译器会直接报错而不是在运行时崩溃。3性能高函数模板是在编译期实例化的。编译器会像生成普通函数一样为你生成具体的机器码。编译器通常会将短小的模板函数内联inline进一步提升执行效率。泛型代码的性能通常与手写的具体类型代码完全一致缺点1代码膨胀编译器会为每一种使用到的类型生成一份独立的函数实例。2编译时间变长模板的解析推导和实例化都在编译期进行。3报错信息难懂当模板出现类型错误时编译器会打印出极其冗长的错误信息。4无法分离编译模板的声明和定义无法分离结尾本篇文章中所涉及到的代码gitee链接泛型编程-模板进阶以上就是本文的全部内容了如果对你有所帮助的话请大佬不妨给博主来个“一键三连”这对我是大大的支持也能让博主产出更优质的内容。往期回顾C 泛型世界的两块拼图容器适配器与仿函数总结本文详细讲解了C模板进阶内容涵盖非类型模板参数如size_t、array容器的越界检查、函数与类模板特化全特化、偏特化、模板分离编译问题及函数模板的优缺点。⚡把上面的内容吃透就休息一下吧⚡

相关新闻

影刀RPA新手教程:微博热搜与话题数据定时采集入门

影刀RPA新手教程:微博热搜与话题数据定时采集入门

影刀RPA新手教程:微博热搜与话题数据定时采集入门 想每天自动记录微博热搜榜和话题阅读量,人工盯又累又容易忘,这就是很多人学影刀RPA后想做的第一个定时采集项目。但新手在定时任务上摔的跟头,比在采集指令上多得多:任…

2026/10/7 14:06:01 阅读更多 →
设计稿转代码(D2C)真能替代前端吗?哪些适合自动生成、哪些必须人工

设计稿转代码(D2C)真能替代前端吗?哪些适合自动生成、哪些必须人工

授权与合规声明 本文为技术实践笔记,示例均基于公开文档与自建环境中的实验,不涉及任何未获授权的系统。文中结论仅代表个人实践小结,与所涉厂商无利益关系。转载请注明出处。1. 设计稿转代码为什么突然变热 过去几年"设计稿转代码"…

2026/10/7 14:06:01 阅读更多 →
影刀RPA新手教程:快递物流自动查询实战——批量查单号与异常告警

影刀RPA新手教程:快递物流自动查询实战——批量查单号与异常告警

影刀RPA新手教程:快递物流自动查询实战——批量查单号与异常告警 记识影刀与安装 影刀装完先确认两件事:内置浏览器版本对齐Chrome版本、安装路径无中文无空格。快递查询网站用的不是常见电商平台,有些用的是老旧IE兼容页面,影刀内…

2026/10/7 14:06:01 阅读更多 →

最新新闻

ROS2自主导航语音播放模块:pyttsx3与ffmpeg实战

ROS2自主导航语音播放模块:pyttsx3与ffmpeg实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 15:04:04 阅读更多 →
像写 Controller 一样开发 Java MCP:TaoToken 统一 Key 接入 Solon-AI 的 Java 8 实践

像写 Controller 一样开发 Java MCP:TaoToken 统一 Key 接入 Solon-AI 的 Java 8 实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 15:04:04 阅读更多 →
SpringBoot+Vue小区物业管理系统源码解析与部署实战

SpringBoot+Vue小区物业管理系统源码解析与部署实战

简介:面向高校毕业设计的完整前后端分离项目源码,采用Spring Boot与Vue框架,围绕小区物业服务场景,提供业主信息、缴费、报修等常见业务模块,适合计算机相关专业学生用于毕设参考、二次开发及功能演示。压缩包共760个文…

2026/10/7 15:04:04 阅读更多 →
科研写作素养培育:论文写作体系化教学与硕词AI工具实践优势阐释

科研写作素养培育:论文写作体系化教学与硕词AI工具实践优势阐释

科研写作素养是科研人员的核心底层素养,涵盖科研思维、逻辑建构、学术表达、规范认知、细节把控等多项能力,是长期学术研究与文稿创作积累形成的综合能力。相较于单次论文写作技巧,系统化的科研写作素养,能够支撑科研从业者长期的…

2026/10/7 15:04:04 阅读更多 →
题解:洛谷 P1399 [NOI2013] 快餐店

题解:洛谷 P1399 [NOI2013] 快餐店

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大家订阅我的专栏:算法…

2026/10/7 15:04:04 阅读更多 →
导热硅胶片和导热硅脂到底有什么区别?别再混用了

导热硅胶片和导热硅脂到底有什么区别?别再混用了

电子热设计新手经常混淆导热硅胶片与导热硅脂,甚至在产品上直接替换使用,最终带来可靠性隐患。二者虽然都用于填充热源与散热器之间的缝隙,但形态、使用方式、适用场景完全不同。导热硅脂是膏状流体,依靠油脂填充微观缝隙&#xf…

2026/10/7 15:03:04 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:13 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 11:43:46 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →