C++模板进阶(非类型模板参数 + 模板特化)

news2024/10/5 16:32:34

我们另一篇模板初阶介绍链接:http://t.csdn.cn/Ox8Dm

目录

 一、非类型模板参数

1.1 非类型模板参数概念

1.2 模板类型的静态数组 

二、模板特化

2.1 函数模板特化

2.2 类模板特化

2.2.1 类模板全特化

2.2.2 类模板半特化(偏特化)

 2.2.3模板特化应用场景


 一、非类型模板参数

1.1 非类型模板参数概念

模板参数分为类型参数和非类型参数!

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

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

1.2 模板类型的静态数组 

将数组封装成类,类成员是一个数组!我们可以通过传非类型模板参数定义数组的大小!这样我们手动调控静态数组大小!

template<class T,size_t N=10>
class Array
{
public:
	Array()
	{
		for (size_t i = 0;i <_size;i++)
		{
			_arr[i] = i+1;
		}
	}
	T operator[](size_t n)
	{
		assert(n < _size);//只要发生越界直接报错
		return _arr[n];
	}
	size_t size()const
	{
		return _size;
	}
private:
	T _arr[N];
	size_t _size=N;
};

测试一下效果:


二、模板特化

2.1 函数模板特化

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

我们实现了一个比较模板函数,下面我们预比较不同类型的数据:

//模板函数
template<class T>
bool Less(const T& left, const T& right)
{
	return left < right;
}

void Test2()
{
    //整形
	cout << " Less(1, 2)="<<Less(1, 2) << endl;

	//日期类
    Date d1(2023,1,8);
	Date d2(2023,1,9);
	cout << "Less(d1,d2)="<< Less(d1, d2) << endl;
    
    //日期类,但传的是地址
	Date* p1 = &d1;
	Date* p2 = &d2;
	cout <<"Less(p1, p2)="<< Less(p1, p2) << endl;
}

很明显我们发现同样希望比较日期类,第二个比较直接用Date类型,第三个用的是Date*,但是比较结果却相反!这与我们的期望不同!思考发现,原来第三个比较的并不是日期类,而是二者的地址,所以结果不同!这种情况下,我们理想的是比较*left与*right,但是模板函数参数限定了它的比较形式!也就是说范式的模板函数不能解决所有的比较,我们需要特例化!也就是特化函数模板!这里我们需要特化Date*比较!

函数模板的特化步骤:

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

特化Date* 代码:

template<class T>
bool Less(const T& left, const T& right)
{
	return left < right;
}

template<>//这个模板列表不能省去!
bool Less<Date*>(Date* const& left, Date* const& right)
{
	return *left < *right;
}

特化后比较结果:


2.2 类模板特化

2.2.1 类模板全特化

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

//全特化测试
void Test3()
{
	Data<int, int> d1;
	Data<int, char> d2;
}

 

若模板参数匹配特化的类模板参数,则优先调用特化类模板!


2.2.2 类模板半特化(偏特化)

偏特化就是部分类模板参数具体化!如果类模板所传参数满足特化模板对应位置具体化参数!则优先调用特化模板!

//一般模板函数
template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

//偏特化,部分位置参数确定
template <class T1>
class Data<T1, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};

//指针/引用偏特化
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

template <class T1,class 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;
};

//偏特化测试
void Test4()
{
	Data<double, int> d1; // 调用特化的int版本
	Data<int, double> d2; // 调用基础的模板
	Data<int*, int*> d3; // 调用特化的指针版本
	Data<int&, int&> d4(1, 2); // 调用特化的指针版本
}

 


 2.2.3模板特化应用场景

如果我们拿到的类型是日期类的地址,我们想要less比较的是*left和*right !但库中的一般模板参数只是比较left和right!也就是只比较地址!这样不能满足我们的需求,所以必须特化!

#include<vector>
#include<algorithm>//sort
#include <functional>//less
//模板特化应用场景
template<>
class less<Date*>
{
public:
	bool operator()(Date* left,Date* right)
	{
		return *left > *right;
	}
};
void Test5()
{
	Date d1(2023, 1, 8);
	Date d2(2023, 1, 9);
	Date d3(2022, 12, 31);
	vector<Date*> v;
	v.push_back(&d1);
	v.push_back(&d2);
	v.push_back(&d3);
	sort(v.begin(), v.end(), less<Date*>());
	for (auto& e : v)
	{
		cout << *e;
	}
}


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

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

相关文章

Facebook运营主页需要注意的几个问题

Facebook运营主页需要注意的几个问题主页的权重和流量都是决定流量的关键因素&#xff0c;也就是我们常说的引流&#xff0c;而流量又是需要转化的&#xff0c;因为只有用户认可你&#xff0c;才会有更多的点击、收藏、分享和主页的链接。在社交媒体时代要想更好地推广品牌产品…

openssl 编译动态库 win11 vs2022

官网 openssl官网 安装perl activestate_perl_官网 需要下载cli_installer 下载后双击下载好的exe 一般就是下面这个执行文件 state-remote-installer.exe 需要按照提示在powershell中执行网页提示的命令。 安装nasm nasm官网 以管理员方式运行安装 并加入环境变量中…

《MySQL高级篇》十、数据库其他调优策略

文章目录1.数据库调优的措施1.1调优的目标1.2 如何定位调优问题1.3 调优的维度和步骤第1步&#xff1a;选择适合的DBMS第2步:优化表设计第3步:优化逻辑查询第4步:优化物理查询第5步:使用Redis或 Memcached 作为缓存第6步&#xff1a;库级优化2. 优化MySQL服务器2.1 优化服务器硬…

定时任务、cron表达式、springBoot整合定时任务和异步任务-59

一&#xff1a;定时任务 1.1 官网地址 http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html 1.2 cron表达式 Cron表达式是一个字符串&#xff0c;字符串以5或6个空格隔开&#xff0c;分为6或7个域&#xff0c;每一个域代表一个含义&am…

【Nacos】一文为你揭露它的强大

注&#xff1a;为什么要使用nacos作为注册中心呢&#xff1f;这样的好处在哪呢&#xff1f;一、 什么是nacosNacos 是 Dynamic Naming and Configuration Service 的首字母简称&#xff1b;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您…

java 方法看这一篇文章就够了

第一章 方法概念 1实现特定功能的一段代码,可反复被调用计算机 — 模拟现实 — 通过软件控制硬件 比如豆浆机 — 里面的微控制器 — 控制豆浆机 右图面板上有很多种模式 每一种模式对应不同的搅拌次数、搅拌时间、烧水温度等… 这些硬件的动作都需要软件的控制 硬件的每一种模式…

el-table使用sortablejs实现行、列拖拽

效果图 代码如下 <script src"//unpkg.com/sortablejs1.7.0/Sortable.js"></script> <script src"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <link rel"stylesheet" href"//unpkg.com/eleme…

文件或目录损坏且无法读取?正确恢复文件的4个方法

你有没有遇到过“文件损坏已无法读取”的提示窗口&#xff1f;相信使用电脑的你&#xff0c;或多或少都会遇到过&#xff0c;尤其是我们使用硬盘或者移动硬盘的时候。 遇到这种问题&#xff0c;我们第一时间不是按照系统提示去删除或者格式化&#xff0c;而是要寻找合适的方法…

DES算法笔记

文章目录DES简介FeistelDES算法流程EncipheringKey ScheduleDecipheringThe Cipher Function f(R, K)Triple DES算法OpenSSL接口S-box实现参考资料DES简介 发布文档&#xff1a;FIPS 46-3, 1977 block size: 8 bytes.Key Size: 8 bytes 64 bits, 原本设计每隔7 bits保留一个…

关于string boot项目实训课(准备工作)

一、页面–web页面–java代码之间的逻辑关系 首先在java文件夹下创建一个java类 Controller//类上面要加入注解 public class TestController {GetMapping("login")//对应web请求--localhost:9991/Login//类方法&#xff0c;用于处理逻辑public String login(Strin…

实时Windows AD用户帐户锁定分析器工具

实时帐户锁定工具提供有关域帐户锁定原因的实时报表。本机Windows Active Directory帐户锁定策略是阻止连续、时限性、寻求登录的密码猜测尝试的一种实用方法&#xff0c;这会由于使用错误的密码而导致帐户锁定。帐户锁定的其他原因可能包括&#xff1a;由于采用严格的密码设置…

【项目】 改造原前端ViewUI框架,使其支持ElementUI 与 Avue

一、背景说明 因为原来前端的同事习惯用&#xff0c;ViewUI框架&#xff0c;于是基线版本的项目&#xff0c;都是使用的ViewUI框架搭建的。 但是&#xff0c;这个ViewUI的表格&#xff0c;是引用的第三方的vux的框架&#xff0c;在网上很少人使用&#xff0c;所以遇到问题&…

如果为产业互联网时代的发展寻找一个注脚的话,新产业无疑是一个最主要的特征

如果为产业互联网时代的发展寻找一个注脚的话&#xff0c;新产业无疑是一个最主要的特征。在这个时代&#xff0c;诸多原本看似无法改变的产业有了改变的可能性&#xff0c;诸多看似无法破解的痛点和难题有了新的解决方案。如果一定要找到导致这一蜕变的根本原因的话&#xff0…

用户积分和积分排行榜功能微服务实现

文章目录需求分析什么是积分积分的获取为啥需要积分服务数据库表创建 ms-points 积分微服务新增用户积分功能用户积分实体积分控制层积分业务逻辑层数据交互mapper层网关 ms-gateway 服务添加积分微服务路由用户服务中添加用户积分逻辑项目测试积分排行榜TopN(关系型数据库)构造…

記錄centos8 升級Python3.6到Python3.9以及可能遇到的問題

目录下载Python3.9.9可能出現的問題及解決方案安裝python3.9可能出現的問題及解決方案建立Python3和pip3的软鏈接:查看Python3和Pip3是否正确的被安装&#xff1a;将/usr/local/python3/bin加入PATHCentos8-默认的Python、python2版本为2.7&#xff0c;python3版本為3.6&#x…

迭代器深入理解

目录 vector 例子引入 迭代器的价值 通过vector和list 迭代器的差异再次深入理解 vector 例子引入 在学习vector底层erase&#xff0c;碰到迭代器失效的时候我有个疑惑&#xff0c;为什么sgi 版&#xff08;Linux g使用的&#xff09;库里实现的迭代器对于有些迭代器失效情…

threejs教程(一)

插件安装 npm i three项目引入 这里我随便找的VUE项目练习的 import * as THREE from "three";大致介绍一下threejs的逻辑 一般我们用它是来搭建三维模型的,搭建三维模型就需要的三个要素 场景(scene) 渲染器(renderer) 和相机(camera) 场景简单理解就是唱戏的戏台…

【C++升级之路】第六篇:模板初阶(函数模板类模板)

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;泛型编程的概念&#xff0c;函数模板的概念、格式、原理和基础使用方法&#xff0c;类模板的格式和基础使用…

Java一维数组的定义、赋值和初始化

当数组中每个元素都只带有一个下标时&#xff0c;这种数组就是“一维数组”。一维数组&#xff08;one-dimensional array&#xff09;实质上是一组相同类型数据的线性集合&#xff0c;是数组中最简单的一种数组。 数组是引用数据类型&#xff0c;引用数据类型在使用之前一定要…

Linux操作系统--文本编辑器(保姆级教程)

文本编辑器 Linux是一种文本驱动的操作系统。用户在使用Linux过程中经常需要编辑文本&#xff0c;比如编写脚本文件来执行几条命令行&#xff0c;写电子邮件&#xff0c;创建C语言源程学等&#xff0c;因此&#xff0c;必须熟悉至少一种文本编辑器以便高效地输入和修改文本文件…