C++:模板 II(非类型模板参数,特化,分离编译)

news2024/11/27 14:37:12

目录

非类型模板参数

模板的特化

函数模板特化

类模板特化 

全特化

偏特化

引用特化

指针特化

模板分离编译


非类型模板参数

什么是非类型模板参数?

顾名思义,它的类型形参并不是一个类型,就是用一个常量来作为类模板或函数模板的一个参数

template<class T, size_t N = 10>
class array
{
public:
	// ...
private:
	T _array[N];
	size_t _size;
};

 上面的这个类模板里就是有一个size_t N,默认是10,代表开10个数组

注意:

1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的

2. 非类型的模板参数必须在编译期就能确定结果

模板的特化

特化是什么?

模板的特化可以说就是模板的特殊化处理

我们通常情况下使用模板可以实现一些与类型无关的代码

但如果有特殊类型可能会得到一些错误的结果,例如:

template<class T>
bool Less(T left, T 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;
}

 这里前面两个都可以比较正确

但是到了最后的Date* p1和p2的比较就会出问题

这时候把p1和p2传进去比较的不是它指向的内容,而是比较的地址,所以这个比较是随机的也是错误的!

函数模板特化

这时候我们就需要特化一个Less函数来支持它的比较

template<>
bool Less<Date*>(Date* left, Date* right)
{
	return *left < *right;
}

函数模板的特化步骤:

1. 首先要有一个基础的函数模板

2. 关键字template后面要有<>

3. 函数名后面跟一个<>,<>中指定需要特化的类型

4. 函数形参的类型必须要和特化的类型相同,如果不同编译器会报错

这时候我们就可以让前面的Date*指针走我们特化的这个函数,结果就正确了

当然我们也可以直接重载Less即可

bool Less(Date* left, Date* right)
{
    return *left < *right;
}

这种代码实现更为简单明了,代码可读性高,容易书写

对于参数类型复杂的函数模板,特化时特别给出,因此函数模板不建议特化

类模板特化 

全特化

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

类模板的特化和函数模板特化的步骤写法一致

全特化就是将模板参数列表中所有参数都确定化

偏特化

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

偏特化就是有特化,但是没有全部特化

这里就是将第二个参数特化为int,第一个不变,但是要写到特化的<>中

引用特化
template <classT1, 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;
};

这个特化是特化为了引用,所以若是调用的引用类型就会调用到这个模板

Data<int&, int&> d4(1, 2);
指针特化
template <class T1, class T2>
class Data <T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

 这个特化是特化为了指针,所以若是调用的指针类型就会调用到这个模板

Data<int *, int*> d3;

模板分离编译

若是有如下场景

a.h

template<class T>
T Add(const T& left, const T& right);

a.cpp

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

main.cpp 

#include"a.h"

int main()
{
	Add(1, 2);
	Add(1.0, 2.0);
	return 0;
}

这时候运行就会出现错误

此时的a.cpp形参a.obj,main.cpp形参main.obj

在编译器链接的时候,会将多个合并成一个函数地址链接起来

但是在a.cpp中并没有实例化该Add函数,所以并不会生成具体的Add函数

而在main.cpp中,在链接是并没有找到Add函数的定义(没有被a.cpp实例化),因此链接时报错

解决方法

1. 将声明和定义放到同一个文件下(xxx.hpp或者xxx.h中都可以),比较推荐该方法

2. 模板定义的位置显示实例化(不适用,不推荐)


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

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

相关文章

(软件测试)基础2

1.等价类划分法 步骤&#xff1a; 2.编写数据用例 例题&#xff1a;参考基础1中的手机号实例 2.边界值分析法

p8 Run的流程和Docker原理

docker run的运行原理图 docker是怎么工作的&#xff1f; docker是一个cs的一个结构的系统docker的守护进程运行在宿主机上面通过socket进行访问 其实就是看下面的这个图&#xff0c;通过客户端的命令来操作docker的守护进程然后启动一些容器&#xff0c;默认容器是不启动的 …

凡图公益行:凡图家庭教育以行动筑梦,点亮孩子心中的光芒

在教育的路上&#xff0c;每一步都承载着未来的希望&#xff0c;凡图(山东)教育科技集团有限公司一直致力于为每一个孩子及家庭提供最优质的心理咨询服务。 在这样的背景下&#xff0c;凡图家庭教育以独特的使命感和责任感&#xff0c;成为了众多家庭信赖的伙伴。 也因此成为…

【 打印菱形】打印菱形

打印菱形 C语言实现&#xff0c;具体代码&#xff1a; #include<stdio.h>int main(){int i,j,k;// 上半部分for(i0;i<3;i){for(j0;j<2-i;j)printf(" ");for(k0;k<2*i;k)printf("*");printf("\n");}// 下半部分for(i0;i<2;i)…

文件上传真hard

一、SpringMVC实现文件上传 1.1.项目结构 1.1.2 控制器方法 RequestMapping("/upload1.do")public ModelAndView upload1(RequestParam("file1") MultipartFile f1) throws IOException {//获取文件名称String originalFilename f1.getOriginalFilename(…

数据库之Mybatis映射文件、动态SQL

目录 1.XML映射文件 2.动态SQL 1.XML映射文件 之前我们执行sql语句是通过注解的方式&#xff0c;还有另外一种方式是通过XML配置文件执行sql语句&#xff0c;这份文件在Mybatis中也称为XML映射文件。 XML配置文件的规范&#xff1a;只有这三条规范都正确的情况下&#xff0…

基于SSM的二手车交易管理系统的设计与实现 (含源码+sql+视频导入教程+论文)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的二手车交易管理系统拥有两种角色&#xff1a;管理员和用户 管理员&#xff1a;二手车信息管理、类型管理、定金支付管理、预约到店管理、二手车评估管理、论坛管理、系统管理、…

数据库Mybatis基础操作

目录 基础操作 删除 预编译SQL 增、改、查 自动封装 基础操作 环境准备 删除 根据主键动态删除数据&#xff1a;使用了mybatis中的参数占位符#{ }&#xff0c;里面是传进去的参数。 单元测试&#xff1a; 另外&#xff0c;这个方法是有返回值的&#xff0c;返回这次操作…

stack/queue容器

stack容器 std::stack 是 C 标准库中定义的容器适配器&#xff08;container adaptor&#xff09;&#xff0c;它基于其他底层容器&#xff08;如 std::deque、std::list 或 std::vector&#xff09;实现了后进先出&#xff08;LIFO&#xff09;的数据结构。栈容器没有迭代器&…

JavaScript_10_练习:轮播图

效果图 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>练习&#xff1a;轮播图</title>…

OD C卷 - 查找一个有向网络的头节点和尾节点

查找一个有向网络的头节点和尾节点 &#xff08;200&#xff09; 在一个有向图中&#xff0c;有向边用两个整数表示&#xff0c;第一个整数表示起始节点&#xff0c;第二个整数表示终止节点&#xff1b;图中只有一个头节点&#xff0c;一个或者多个尾节点&#xff1b;图可能存…

Linux系统信息排查

目录 介绍步骤 介绍 1、熟悉查看CPU信息、操作系统信息、用户信息、特殊权限账户、启动项和任务计划的排查命令 2、在进行受害主机排查时&#xff0c;首先要对主机系统进行基本排查&#xff0c;方便对受害主机有一个初步的了解。 3、利用lscpu和uname -a查看系统硬件软件基本…

JavaScript(28)——正则表达式

定义正则表达式语法&#xff1a; const 变量名 /表达式/ 判断是否有符合规则的字符串&#xff1a; test()方法 用来查看正则表达式与指定的字符串是否匹配 语法&#xff1a; regObj.test(被检测的字符串) //返回布尔值 regObj.exec(字符串) //返回的是数组 <script>…

基于Docker compose部署Confluence 8.3.4及设置数据持久化存储的总结

基于Docker compose部署Confluence 8.3.4及设置数据持久化存储的总结 一、环境信息二、安装部署三、向导 介绍如何基于Docker、Docker Compose的方式安装部署Confluence 8.3.4&#xff0c;并且设置数据的持久化存储。 一、环境信息 操作系统&#xff1a;CentOS 7.9 Docker Ver…

C++之多态(下)

目录 多态的实现原理 多态的拓展 单继承中的多态 多继承中的多态 上期&#xff0c;我们学习了多态的基本概念&#xff0c;本期我们来学习多态的实现原理。 多态的实现原理 class Base { public:virtual void func1(){cout << "Base::func1()" <<…

CUTLASS 中的 47_ampere_gemm_universal_streamk 示例

前一篇文章介绍了 Stream-K: Work-centric Parallel Decomposition for Dense Matrix-Matrix Multiplication on the GPU 论文&#xff0c;下面对其代码实现进行分析。 cutlass 的 examples/47_ampere_gemm_universal_streamk 展示了 GEMM Stream-K 算法在 Ampere 架构上的使用…

健身房管理系统--论文pf

TOC springboot542健身房管理系统--论文pf 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的广泛…

思特科技:国家宝藏数字体验馆展现东方美学 让“文物活起来”

01      思特科技为“国家宝藏数字体验展”提供“数字技术”支持&#xff0c;带来国宝的数字化演绎。以《国家宝藏》顶级IP为基础&#xff0c;打造的全新沉浸文化项目“国宝数字体验展“&#xff0c;借由文物的视角、站在历史的星河中&#xff0c;探寻时间长河中不变的智慧…

设计模式笔记02(java版)

文章目录 创建者模式单例设计模式 ★单例模式的结构单例模式的实现饿汉式-方式1&#xff08;静态变量方式&#xff09;饿汉式-方式2&#xff08;静态代码块方式&#xff09;懒汉式-方式1&#xff08;线程不安全&#xff09;懒汉式-方式2&#xff08;线程安全&#xff09;懒汉式…

Linux环境安装 JDK

目录 JDK准备 1&#xff09;卸载现有JDK&#xff08;3台节点&#xff09; 2&#xff09;用Xftp工具将JDK导入到hadoop12的/opt/software文件夹下面 3&#xff09;在Linux系统下的opt目录中查看软件包是否导入成功 4&#xff09;解压JDK到/opt/module目录下 5&#xff09;配…