【C++】第十四节—模版进阶(非类型模版参数+模板的特化+模版分离编译+模版总结)

【C++】第十四节—模版进阶(非类型模版参数+模板的特化+模版分离编译+模版总结)

你好,我是云边有个稻草人 

C++—本文章所属专栏,欢迎订阅,持续更新中!

目录

一、非类型模板参数

【非类型模版参数的用处在哪里? 】

【了解array 容器—array和普通数组的区别在哪里?—对越界的检查】

二、模板的特化(特殊化处理)

2.1 概念

2.2 函数模版特化

【函数模版特化可使用,但不推荐】 

2.3 类模版特化

【全特化】

【偏特化】

 【判断走哪个类模版?】

【类模版特化应用实例】

三、模版分离编译

3.1 什么是分离编译

3.2 模板的分离编译

 【分析】

3.3 解决办法

【分离定义扩展阅读】

四、模板总结

【优点】

【缺陷】


正文开始——

一、非类型模板参数

模板参数分为类型形参非类型形参

类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。

非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

注意:浮点数、类对象以及字符串是不允许作为非类型模板参数的。非类型的模板参数必须在编译期就能确认结果。类型模版参数和非类型模版参数都可以用缺省值,但是非类型模版参数是有限制的,只能用整型类型,浮点型,类类型等都是不可以的!
【非类型模版参数的用处在哪里? 】
#include<iostream> using namespace std; //#define N 10//宏定义 //只支持整型 template<class T,size_t N = 10>//非类型模版参数可以给缺省值 class Stack { private: T _a[N]; int _top; }; ////C++20以后才支持浮点数 //template<class T, double N = 10.1>//非类型模版参数可以给缺省值 //class Array //{ //private: //}; int main() { Stack<int,20> st1; Stack<int,200> st2; Stack<int> st3; return 0; }
【了解array 容器—array和普通数组的区别在哪里?—对越界的检查】

二、模板的特化(特殊化处理)

2.1 概念

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理。

比如:实现了一个专门用来进行小于比较的函数模板

class Date { public: Date(int year = 2025, int month = 7, int day = 9) :_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)); } private: int _year; int _month; int _day; }; //函数模版 template<class T> bool Less(T left,T right) { return left < right; } int main() { Date d1(2025, 7, 9); Date d2(2025, 9, 9); Date* p1 = new Date(2025, 8, 9); Date* p2 = new Date(2025, 10, 9); cout << Less(1, 2) << endl;//可以判断,结果正确 cout << Less(d1, d2) << endl;//可以判断,结果正确 cout << Less(p1, p2) << endl;//结果随机。其实这里是对new出来的地址进行比较,当然是随机,那怎么办?—特化! return 0; }

可以看到,Less绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果。上述示例中,p1指向的d1显然小于p2指向的d2对象,但是Less内部并没有比较p1和p2指向的对象内容,而比较的是p1和p2指针的地址,这就无法达到预期而错误。 此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化类模板特化

2.2 函数模版特化

函数模板的特化步骤:

    Read more

    通过URI Scheme实现从Web网页上打开本地C++应用程序(以腾讯会议为例,附完整实现源码)

    通过URI Scheme实现从Web网页上打开本地C++应用程序(以腾讯会议为例,附完整实现源码)

    目录 1、需求描述 2、选择URI Scheme实现 3、何为URI Scheme? 4、将自定义的URL Scheme信息写入注册表的C++源码实现 5、如何实现最开始的3种需求 6、后续需要考虑的细节问题        之前陆续收到一些从Web页面上启动我们C++客户端软件的需求,希望我们能提供一些技术上的支持与协助,支持从Web网页上将我们的C++客户端软件启动起来。于是我大概地研究了相关的实现方法,下面把研究的过程与结果在此做一个分享,希望能给大家提供一个借鉴或参考。 C++软件异常排查从入门到精通系列教程(核心精品专栏,订阅量已达10000多个,欢迎订阅,持续更新...)https://blog.ZEEKLOG.net/chenlycly/article/details/125529931C/C++实战专栏(重点专栏,专栏文章已更新500多篇,订阅量已达8000多个,欢迎订阅,持续更新中...)https://blog.ZEEKLOG.net/

    By Ne0inhk
    【C++】STL之list模拟实现:关于链表容器的双向迭代器你知道多少?

    【C++】STL之list模拟实现:关于链表容器的双向迭代器你知道多少?

    前言: 前面的博客中我已经介绍了STL核心容器之一的list相关接口的使用,今天我们就从底层出发,来模拟实现一下list的那些核心接口函数。同时,也来感受一下list的双向迭代器到底与string和vector的随机迭代器有哪些区别? list容器功能接口介绍:https://blog.ZEEKLOG.net/Miun123/article/details/151685386?spm=1001.2014.3001.5502 废话不多说,我们直接进入今天的正题👇️👇️👇️ list容器深度剖析及模拟实现 我们想要模拟实现list容器,那就要理解list容器的底层结构。前面的博客已经提到,其本质就是一个双向链表,所以,成员变量就应该包含一个记录头节点的指针,以及记录有效节点个数的变量。同时,为了list容器可以满足不同类型的数据,我们将所有的类实现为类模板。 1、定义节点结构 struct创建的类默认所有的成员但是公开的,而节点结构就需要公开被list访问。 template<class T> struct list_node { // 成员变量 T _da

    By Ne0inhk
    2019年信奥赛C++提高组csp-s初赛真题及答案解析(完善程序第1题)

    2019年信奥赛C++提高组csp-s初赛真题及答案解析(完善程序第1题)

    2019年信奥赛C++提高组csp-s初赛真题及答案解析(完善程序第1题) 第1题(匠人的自我修养) 一个匠人决定要学习 n个新技术。要想成功学习一个新技术,他不仅要拥有一定的经验值,而且还必须要先学会若干个相关的技术。学会一个新技术之后,他的经验值会增加一个对应的值。给定每个技术的学习条件和习得后获得的经验值,给定他已有的经验值,请问他最多能学会多少个新技术。 输入第一行有两个数,分别为新技术个数 n(l≤n≤ 10 3 10^3 10

    By Ne0inhk
    纸上谈“型”不如运行识“真”:深入 C++ RTTI 与多态的底层真相!

    纸上谈“型”不如运行识“真”:深入 C++ RTTI 与多态的底层真相!

    文章目录 * 本篇摘要 * RTTI(Run-Time Type Information,运行时类型信息) 介绍 * RTTI 的核心组成 * 1. `typeid` 运算符 * 2. `dynamic_cast` 运算符 * RTTI 如何工作?(底层原理) * ① 编译器为多态类型做了什么? * ② 当我们调用对应接口,RTTI底层是如何实现呢? * **`场景 1:typeid(obj)`** * 场景 2:dynamic_cast<Derived*> ( p ) * `std::type_info` 类简介 * RTTI 的开销与争议 * 优点: * 缺点: * 何时使用 RTTI? * 禁用 RTTI操作 * 为什么非多态类型不支持 RTTI? * 总结

    By Ne0inhk