【CPP】模板(后篇)

news2024/9/21 20:23:19

目录

        • 13.1 非类型模板参数
        • 13.2 函数模板的特化
        • 13.3 类模板的特化
        • 13.4 模板的分离编译

这里是oldking呐呐,感谢阅读口牙!先赞后看,养成习惯!
个人主页:oldking呐呐
专栏主页:深入CPP语法口牙

13.1 非类型模板参数
  • 顾名思义,非类型模板参数就是一个模板的参数,只不过不是类型,而是一个常量,这个常量的具体值会在被编译的时候确定下来,非类型模板参数也可以有缺省值,值得注意的是,在C++20之前,非类型模板参数的类型只能是整型(int,char,bool,short,long等)
template<int n = 10>
class AA
{
private:
	int _aa[n];
};

//C++20支持了浮点数作为非类型模板参数
//template<double n = 10>
//class AA
//{
//private:
//	double _aa = n;
//};

int main()
{
	AA<10> a1;

	AA<> a2;
	//AA a3; (C++20)

	return 0;
}
  • 非类型模板参数比较常用的地方是一个叫做array的容器,其实array和普通的数组几乎没有区别,只是说array对于越界的检查会比普通的数组强得多
int main()
{
	//非类型模板参数是数组的元素个数
	array<int, 10> a1();

	return 0;
}
13.2 函数模板的特化
  • 模版的特化可以理解为模板的重载

  • 比方说

template<class T>
void Less(T a, T b)
{
	return a < b;
}
  • 然后我想实现比较int*下的值,但原本的模板又没有解引用,所以就需要特化
template<>
bool Less<int*>(int* a, int* b)
{
	return *a < *b;
}
  • 这个特化中的类型,只能用已经有的类型,包括内置类型和自定义类型,用未知类型会直接报错

  • 并且,特化的参数要和原模板几乎一样,意思是,特化要求特化能传的,原模版也要能传,只不过编译器会选择特化来调用罢了

  • 不过从根本上说,函数特化其实并不好用,问题就出自上面这条"特化要求特化能传的,原模版也要能传",这就导致了一个重要的问题,假如说原模版使用了传引用传参而不是传值传参,就会出现很多问题
    请添加图片描述

  • 如果执意要用的话只能这么改

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

//因为const修饰的引用不能被修改,所以特化也要给被引用的值加const,这样看起来就会显得很奇怪
//所以还不如直接重载一个函数方便得多
template<>
bool Less<int*>(int* const& a, int* const& b)
{
	return *a < *b;
}
  • 反正都只能传int*,不如直接重载一个来得方便传值就传值,想传引用就传引用
bool Less(int* a, int* b)
{
	return a < b;
}
13.3 类模板的特化
  • 特化分为全特化和偏特化,有点像全缺省和半缺省
template<class T1, class T2>
class A
{
public:
	A()
	{
		cout << "<class T1, class T2>" << endl;
	}
};

//全特化
template<>
class A<int, char>
{
public:
	A()
	{
		cout << "<int, char>" << endl;
	}
};

//半特化
template<class T1>
class A<T1, char>
{
public:
	A()
	{
		cout << "<T1, char>" << endl;
	}
};

template<class T2>
class A<int ,T2>
{
public:
	A()
	{
		cout << "<int ,T2>" << endl;
	}
};

//特殊玩法
template<class T1, class T2>
class A<T1*, T2*>
{
public:
	A()
	{
		cout << "<T1*, T2*>" << endl;
	}
};

template<class T1, class T2>
class A<T1&, T2&>
{
public:
	A()
	{
		cout << "<T1&, T2&>" << endl;
	}
};

template<class T1, class T2>
class A<T1&, T2*>
{
public:
	A()
	{
		cout << "<T1&, T2*>" << endl;
	}
};

int main()
{
	//正常调用
	A<float, double> a1;

	//特化会优先调用最匹配的,也就是全特化,然后才是偏特化
	A<int, char> a2;
	A<float, char> a3;
	A<int, double> a4;
	A<float, double> a5;
	
	//特殊玩法:你甚至可以指定指针和引用(也是偏特化)
	A<float*, double*> a6;
	A<float&, double&> a7;
	A<float*, double&> a8;

	return 0;
}

请添加图片描述

  • 偏特化其实就是在原模版的基础上做一些限制,而全特化则是在偏特化的基础上做更更多的限制,限制到只能使用具体的类型

  • 特化一般用在需要多场景使用的函数/类/仿函数上,比方说既想实现对值的比较,又想实现对指针下值的比较,就可以再特化一个模板出来

  • 模板特化需要注意,例如以下这种情况

template<class T1, class T2>
class A<T1*, T2*>
{
public:
	A()
	{
		cout << "<T1*, T2*>" << endl;
		T1 a;
	}
};
  • 此时这个a是原类型T1而不是T1*,这样设计可以同时在模板里面使用原类型和引用/指针
13.4 模板的分离编译
  • 简单来说

  • 正常函数的声明和定义分离可以正常被调用,因为在链接的过程中,函数是被确定的,是可以被找到的,不像是函数模板一样不被确定,需要临时生成

  • 模板因为含有未知类型,调用的源头会在编译的时候找到函数声明,然后根据传入的参数类型对模板进行实例化,实例化之后接可以直接用

  • 但如果声明和定义分离了,调用的源头会在编译的时候找到函数声明但却没有找到含函数定义,这时候会假设存在这样的函数,但此时定义还是个模板,并没有被实例化,所以在找函数的时候,就会找不到,所以如果要进行声明和定义分离的话,就一定要函数定义实例化,这样才能在链接的时候有函数可找
    请添加图片描述

  • 一般显式实例化只需要在定义的下面这么写就行

//func.cpp
#include"func.h"
#include<iostream>
using namespace std;

//模板的定义
template<class T>
void func(const T&, const T&)
{
	cout << "void func(const T&, const T&)" << endl;
}

//显式实例化
template  //这个是作为函数模板1显式实例化的标志
void func(const int&, const int&);  //这里要填入具体参数

请添加图片描述

  • 所以事实上我们还是建议在.h直接定义函数模板,最好还是不要在.cpp里显式实例化

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

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

相关文章

第二十六篇——九地篇:九种形势的应对之道

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 地势的维度重新阐述了懂得人心的重要性&#xff0c;道久其归一为为别人。…

个人随想-gpt-o1大模型中推理链的一个落地实现

​首先祝大家中秋节快乐。 最近openai又推出了新的模型openai o1​还有它的mini版。官网的介绍&#xff0c;就是它的推理能力很强&#xff0c;比gpt-4o​有很大的提升。 最近也跟同行在聊这个o1&#xff0c;​看看落地方面有哪些可行性。在我们自己的实验上&#xff0c;把o1用…

Python画笔案例-052 绘制彩色递归六边形

1、绘制彩色递归六边形 通过 python 的turtle 库绘制 彩色递归六边形&#xff0c;如下图&#xff1a; 2、实现代码 绘制彩色递归六边形&#xff0c;以下为实现代码&#xff1a; """彩色递归六边形.py """ import turtledef draw_circle(radius,…

【自动化测试】移动app的分层测试以及自动遍历的基本概念

引言 移动应用的分层测试是一种系统化的测试方法&#xff0c;它将测试过程分解为不同的层次&#xff0c;以确保应用在每个层面上都符合设计要求和用户期望 文章目录 引言一、移动app的分层测试1.1 单元测试&#xff08;Unit Testing&#xff09;1.2 集成测试&#xff08;Integr…

甲骨文创始人埃里森:人工智能终有一天会追踪你的一举一动

9月17日消息&#xff0c;据外电报道&#xff0c;甲骨文创始人拉里埃里森在甲骨文财务分析师会议上表示&#xff0c;他预计人工智能有一天将为大规模执法监控网络提供动力。“我们将进行监督。”他说。“每一位警察都将随时受到监督&#xff0c;如果有问题&#xff0c;人工智能会…

人工智能辅助汽车造型设计

随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;在各个领域的应用越来越广泛&#xff0c;汽车设计行业也不例外。尤其在车辆外观造型设计中&#xff0c;AI正在成为设计师的重要助手&#xff0c;通过提供强大的工具和独特的创意方式&#xff0c;革新了传统设…

算法之搜索--最长公共子序列LCS

最长公共子序列&#xff08;longest common sequence&#xff09;:可以不连续 最长公共子串&#xff08;longest common substring&#xff09;&#xff1a;连续 demo for (int i 1;i<lena;i){for (int j 1;j<lenb;j){if(a[i-1]b[j-1]){dp[i][j]dp[i-1][j-1]1;}el…

神奇的Serializable接口,为什么有时候网络传输不用实现Serializable,有时候又需要?

大家好&#xff0c;这里是小奏,觉得文章不错可以关注公众号小奏技术 背景 其他大家在初学java的时候肯定是接触过Serializable接口的&#xff0c;这个接口是一个标记接口&#xff0c;没有任何方法&#xff0c;只是一个标记&#xff0c;用来标记一个类可以被序列化&#xff0c;…

深入解析代理模式:静态代理、JDK 动态代理和 CGLIB 的全方位对比!

代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它提供了对象的替身&#xff0c;即代理对象来控制对实际对象的访问。通过代理对象&#xff0c;可以在不修改目标对象的情况下&#xff0c;扩展或控制其功能。例如&#xff0c;代理模式可以用于延…

JDBC的介绍和连接MySQL数据库

目录 1. 为什么学习JDBC 1.1 数据存储​编辑​编辑 1.2 数据操作​编辑 2. JDBC概述 2.1 JDBC概念 2.2 JDBC 核心组成 3. 实现 JDBC 3.1 JDBC 搭建步骤 3.2 详细演示 3.3 核心API 3.3.1 Driver​ 3.3.2 Connection​ 3.3.3 Statament​ 3.3.4 PreparedStatement …

嵌入式单片机中can总线调试方法

大家好,今天将向大家介绍如何使用STM32F4自带的CAN控制器实现两个开发板之间的CAN通信。 1.CAN CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO 11898),是国际上应用最广泛的…

大模型笔记03--快速体验dify

大模型笔记03--快速体验dify 介绍部署&测试部署 dify测试dify对接本地ollama大模型对接阿里云千问大模型在个人网站中嵌入dify智能客服 注意事项说明 介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;…

优化 OR 条件过多导致的查询超时

优化 OR 条件过多导致的查询超时 文章目录 优化 OR 条件过多导致的查询超时背景问题分析方案分析方案一&#xff1a;入参去重方案二&#xff1a;分页或者分批查询方案三&#xff1a;UNION 代替 OR方案四&#xff1a;IN 代替 OR1. 分别对列进行 IN 查询&#xff0c;在代码中进行…

同一Python脚本中训练多个模型时的 wandb 配置错误解决方案

文章目录 摘要背景介绍报错信息wandb 模型训练名 摘要 在机器学习项目中&#xff0c;使用Python脚本训练多个模型时&#xff0c;可能会遇到WandB&#xff08;Weights and Biases&#xff09;配置错误&#xff0c;尤其是在训练多个模型参数大小不一致的情况下。 本文将介绍如何…

Vue学习记录之三(ref全家桶)

ref、reactive是在 setup() 声明组件内部状态用的&#xff0c; 这些变量通常都要 return 出去&#xff0c;除了供 < template > 或渲染函数渲染视图&#xff0c;也可以作为 props 或 emit 参数 在组件间传递。它们的值变更可触发页面渲染。 ref &#xff1a;是一个函数&…

Get包中的根组件

文章目录 1. 知识回顾2. 使用方法2.1 源码分析2.2 常用属性 3. 示例代码4. 内容总结 我们在上一章回中介绍了"Get包简介"相关的内容&#xff0c;本章回中将介绍GetMaterialApp组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 知识回顾 我们在上一章回中已经…

Unity webgl跨域问题 unity使用nginx设置跨域 ,修改请求头

跨域 什么是跨域 跨域是指浏览器因安全策略限制&#xff0c;阻止一个域下的网页访问另一个域下的资源。 一些常见的跨域情况&#xff1a; 协议不同 从 http://example.com 请求 https://example.com。域名不同 从 http://example.com 请求 http://anotherdomain.com。端口不…

Village Exteriors Kit 中世纪乡村房屋场景模型

此模块化工具包就是你一直在寻找的适合建造所有中世纪幻想村庄和城市建筑所需要的工具包。 皇家园区 - 村庄外饰套件的模型和纹理插件资源包 酒馆和客栈、魔法商店、市政大厅、公会大厅、布莱克史密斯锻造厂、百货商店、珠宝商店、药店、草药师、银行、铠甲、弗莱切、马厩、桌…

list从0到1的突破

目录 前言 1.list的介绍 2.list的常见接口 2.1 构造函数&#xff08; (constructor)&#xff09; 接口说明 2.2 list iterator 的使用 2.3 list capacity 2.4 list element access 2.5 list modifiers 3.list的迭代器失效 附整套练习源码 结束语 前言 前面我们学习…

Defining Constraints with ObjectProperties

步骤4&#xff1a;使用对象定义约束 物业 您可以创建时间和放置约束&#xff0c;如本教程所示。你也可以 更改单元格的属性以控制Vivado实现如何处理它们。许多 物理约束被定义为单元对象的属性。 例如&#xff0c;如果您在设计中发现RAM存在时序问题&#xff0c;为了避免重新合…