【C++模板进阶】

news2024/10/6 22:22:18

目录

  • 一、模板使用时的一个小注意点
  • 二、非类型模板参数
  • 三、类模板的特化
    • 3.1函数模板的特化
    • 3.2类模板的特化
      • 3.2.1全特化
      • 3.2.2偏特化
  • 四、模板的分离编译
    • 4.1模板不支持分离编译
    • 4.2模板分离编译报错的分析
    • 4.2解决方案
  • 五、模板的总结

一、模板使用时的一个小注意点

在使用模板时,在有些场景下需要加上typename来告诉编译器这里是类型,否则会编译不通过。如:我想写一个不只是针对vector类型打印数据该怎么改写上面的代码呢?

#include<iostream>
using namespace std;

#include<vector>

void Print(const vector<int>& v)
{
	vector<int>::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
	}
	cout<<endl;
}
int main()
{
	vector<int> v;

	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);

	Print(v);
	return 0;
}

首先对于泛型编程的思想一般都会考虑到用模板,所以一般我们都会这么改写代码。如:

#include<iostream>
using namespace std;

#include<vector>
template<class Container>
void Print(const Container& v)
{
	Container::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		it++;
	}
	cout<<endl;
}
int main()
{
	vector<int> v;

	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);

	Print(v);
	return 0;
}

但是呢这种代码连编译都通过不了。如:
在这里插入图片描述
为什呢?
其实是编译器不知道Container::const_iterator这个是类型还是对象
需要在前面加上typename告诉编译器这个是类型,等模板实例化后再去找。如:
在这里插入图片描述

二、非类型模板参数

假设有这样一个场景,我需要创建2个静态的顺序表。一个顺序表的容量是10个,另一个是1000个,该怎么玩呢?按照常规的方法肯定是玩不了的,这时就需要非类型模板参数了。可以这么玩。如:

namespace Ting
{
	template<class T,size_t N>
	class vector
	{
	private:
		T _arr[N];
		size_t capapcity;
	};
}

int main()
{
	Ting::vector<int, 10> v1;
	Ting::vector<int, 1000> v2;
	return 0;
}

在这里插入图片描述
注意:

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  2. 非类型的模板参数必须在编译期就能确认结果且不能被修改。

三、类模板的特化

3.1函数模板的特化

直接先看代码,见一见猪跑。

//函数模板的特化
template<class T>
bool Less(T x, T y)
{
	return x < y;
}

//对函数模板进行特化
template<>
bool Less<int*>(int* x, int* y)
{
	return *x < *y;
}
int main()
{
	int a = 2, b = 1;
	cout << Less(&a, &b) << endl;
	return 0;
}

乍一看是不是感觉函数模板特化有点与函数重载类似?感觉这个没啥用,但是这个是错觉。如:

//函数模板的特化
template<class T>
bool Less(T x, T y)
{
	return x < y;
}

//对函数模板进行特化
template<class T>
bool Less(T* x, T* y)
{
	return *x < *y;
}
int main()
{
	int a = 2, b = 1;
	double c = 2.1, d = 2.2;

	cout << Less(&a, &b) << endl;
	cout << Less(&c, &d) << endl;
	return 0;
}

这种写法比函数重载要方便多了。
函数模板的特化步骤:

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

3.2类模板的特化

类模板的特化的步骤:
1.必须要有基础的类模板
2.关键字template后面接一对空的尖括号<>
3.类名后跟一对尖括号<>,尖括号中指定需要特化的类型。
类模板的特化分为:全特化和偏特化

3.2.1全特化

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

//函数模板的全特化
template<class T1,class T2>
class Ting
{
public:
	Ting()
	{
		cout << "Ting<T1,T2>" << endl;
	}
};
template<>
class Ting<int,char>
{
public:
	Ting()
	{
		cout << "Ting<int,char>" << endl;
	}
};
template<>
class Ting<double, char>
{
public:
	Ting()
	{
		cout << "Ting<double,char>" << endl;
	}
};

int main()
{
	Ting<int, float> zft01;
	Ting<double, char> zft02;
	Ting<int, char> zft03;
	Ting<float, int> zft04;
	return 0;
}

3.2.2偏特化

//函数模板的偏特化
template<class T1, class T2>
class Ting
{
public:
	Ting()
	{
		cout << "Ting<T1,T2>" << endl;
	}
};

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

template<class T1>
class Ting<T1, double>
{
public:
	Ting()
	{
		cout << "Ting<T1,double>" << endl;
	}
};

//还可以对某种类型参数做进一步限制 如:
template<class T1,class T2>
class Ting<T1*,T2*>
{
public:
	Ting()
	{
		cout << "Ting<T1*,T2*>" << endl;
	}
};

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

int main()
{
	return 0;
}

四、模板的分离编译

4.1模板不支持分离编译

比如有这样一个Add函数。如:
.h文件

#pragma once
template<class T>
T Add(T x, T y);

.cpp文件

#include"Add.h"

template<class T>
T Add(T x, T y)
{
	return x + y;
}

测试文件

//模板的分离编译
#include"Add.h"
int main()
{
	cout << Add(1, 2) << endl;
	return 0;
}

运行时就会出现这样的报错。如:在这里插入图片描述

4.2模板分离编译报错的分析

为什么会这样呢?
分析:
C/C++程序要运行,一般要经历一下步骤:
预处理—>编译—>汇编—>链接

编译:对程序按照语言特性进行词法、语法、语义分析,错误检查无误后生成汇编代码。注意头文件不参与编译,编译器对工程中的多个源文件是分离开单独编译的。
链接:将多个obj文件合成一个,并处理没有解决的地址问题。
在这里插入图片描述

4.2解决方案

第一种方法:显示实例化
.cpp文件

#include"Add.h"

template<class T>
T Add(T x, T y)
{
	return x + y;
}

//显示实例化
template
int Add(int x,int y);
int Add(double x, double y);

(以上的方法不推荐)
第二种方法:将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。

五、模板的总结

【优点】

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性
    【缺陷】
  3. 模板会导致代码膨胀问题,也会导致编译时间变长
  4. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

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

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

相关文章

创建Electron项目

一、使用vite 构建 electron项目 npm init vitelatest Need to install the following packages:create-vitelatest Ok to proceed? (y) y √ Project name: ... CertificateDownload √ Package name: ... certificatedownload √ Select a framework: Vue √ Select a var…

java正则表达式「.*?」匹配什么

先说结论&#xff1a;以非贪婪的方式匹配正则表达式".*" 举例子&#xff1a; String s "abdcababc"; String regx1 "ab(.*)c"; String regx2 "ab(.*?)c"; Pattern pattern1 Pattern.compile(regx1); Pattern pattern2 Pattern…

分组排序及首单时间计算

import pandas as pd import numpy as np downpath/Users/kangyongqing/Downloads/ downfile20230725_105033.csvddpd.read_csv(downpathdownfile) dd.rename(columns{student_user_id:学生id},inplaceTrue) result[] for i in range(dd.shape[0]):user,feetimedd.loc[i,[学生…

AES-CTR加密模式介绍 例题

文章目录 CTR&#xff08;Counter mode&#xff0c;CTR&#xff09;计数器模式题目一题目描述&#xff1a;题目分析&#xff1a; 浅记一下 CTR&#xff08;Counter mode&#xff0c;CTR&#xff09;计数器模式 原理&#xff1a; CTR将块密码变为流密码。它通过递增一个加密计数…

防御第三天

1.总结当堂NAT与双机热备原理&#xff0c;形成思维导图 2.完成课堂NAT与双机热备实验 fw1: <USG6000V1>sy [USG6000V1]int g0/0/0 [USG6000V1-GigabitEthernet0/0/0]ip add 192.168.18.2 24 [USG6000V1-GigabitEthernet0/0/0]service-manage all permit (地址无所谓&…

NVM下安装NPM、CNPM详解与坑不是内部命令

设置npm的全局安装路径&#xff1a;有了可以不设置 npm config set prefix "H:\A-work\nvm\npm"C盘用户文件夹&#xff08;C:\Users[name]&#xff09;下会生成一个.npmrc的文件&#xff0c;用记事本打开后可以看到如下内容&#xff1a; 配置环境变量&#xff08;重…

Sip IP网络对讲广播模块,sip网络寻呼话筒音频模块

Sip IP网络对讲广播模块&#xff0c;sip网络寻呼话筒音频模块 模块介绍 SV-2401VP和SV-2403VPIP网络对讲广播模块是一款通用的独立SIP音频功能模块&#xff0c;可以轻松地嵌入到OEM产品中。该模块对来自网络的SIP协议及RTP音频流进行编解码。 该模块支持多种网络协议和音频编…

AdaBoost的求解流程

对于任意Boosting算法&#xff0c;都需要明确以下几点&#xff1a; ① 损失函数&#x1d43f;(&#x1d465;,&#x1d466;)的表达式是什么&#xff1f;损失函数如何影响模型构建&#xff1f; ② 弱评估器&#x1d453;(&#x1d465;)是什么&#xff0c;当下boosting算法使用…

这是一个小程序求助帖

求助帖 请问各位大佬们&#xff0c;在vscode中运行android模拟器&#xff0c;报错&#xff1a;执行emulator命令失败, 错误信息&#xff1a;Error: spawn C:\WINDOWS\system32\cmd.exe ENOENT 该如何解决。环境变量什么的我都已经配置过了&#xff0c;电脑也重启过了&#xff…

Rman配置参数详解

using target database control file instead of recovery catalog指的是使用目标数据库控制文件代替恢复目录 1、CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default 设置rman备份过期条件&#xff1a;是用来决定那些备份不再需要了&#xff0c;它一共有三种可选项&…

mybatisPlus之自动填充功能及防全表更新与删除插件

自动填充功能 基本介绍 Mybatis-plus自动填充功能是指在数据库表进行增、删、改、查操作时&#xff0c;自动将某些字段的值进行填充。这些字段的值可以是当前时间、登录用户ID等。 在项目中有一些属性&#xff0c;如果我们不希望每次都填充的话&#xff0c;我们可以设置为自…

Cilium系列-5-Cilium替换KubeProxy

系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, 可以进一步提升 Cilium 的网络性能. 具体调优项包括不限于: 启用本地路由(Native Routing)完全替换 KubeProx…

数字身份、分布式存储、跨链技术等将如何推动Web3数据的发展?

Web3数据是基于区块链技术、去中心化、可信任的数据&#xff0c;具有较高的安全性和可信度。随着Web3.0时代的到来&#xff0c;Web3数据将会在金融、物联网、医疗、教育、政务等领域发挥重要的作用。其中&#xff0c;数字身份、分布式存储、跨链技术等将会是Web3数据发展的重要…

【教学类-34-07】20230726拼图(彩色图片+菱形凹凸拼图)3*4格子(中班主题《个别化拼图》偏美术)

作品展示&#xff1a; 背景需求 我尝试将拼图的“圆形凹凸角”变成"正方形凹凸角”&#xff0c;没有成功&#xff0c;但做出了“菱形凹凸角”。 实用性思考&#xff1a; 1、这种菱形凹凸角与正方形结构近似&#xff0c;裁剪难度中等&#xff08;比圆角容易剪&#xff0…

100天软件设计师备考计划

我已经毕业并且刚刚开始工作&#xff0c;目前在一家小公司从事Java开发工作。虽然我的工作轻松&#xff0c;但我希望在空闲时间里能够提升自己。由于我的专业与计算机相关&#xff0c;我有一定的基础&#xff0c;因此我计划在2023年用100天的时间考取软件设计师资格。在学习的过…

GB/T 25000.51解读——软件产品的易用性怎么测?

GB/T 25000.51-2016《软件产品质量要求和测试细则》是申请软件检测CNAS认可一定会用到的一部国家标准。在前面的文章中&#xff0c;我们为大家整体介绍了GB/T 25000.51-2016《软件产品质量要求和测试细则》国家标准的结构和所涵盖的内容以及对软件产品的八大质量特性中的功能性…

怎么在电脑中创建虚拟加密磁盘?

在生活和工作中&#xff0c;我们可以将重要数据存放在电脑加密磁盘中。可是不是每个电脑都拥有加密磁盘的。那么我们该怎么在电脑中创建虚拟加密磁盘呢&#xff1f; 将普通磁盘加密 我们可以将重要数据分类存放在一个磁盘中&#xff0c;随后将该磁盘加密&#xff0c;使其变成加…

Mac 快速生成树形项目结构目录

我这里使用的是通过包管理 Homebrew安装形式。没有安装的话可以自行搜索 Homebrew 安装方式 brew install tree直接到项目的根目录执行 tree 命令 tree 效果如下&#xff1a; or &#xff1a; tree -CfL 3效果如下&#xff1a;

Java的第十三篇文章——JAVA多线程

目录 学习目标 1. 线程的基本概念 1.1 进程 1.2 线程 2. Java实现线程程序 2.1 java.lang.Thread类 2.2 线程的内存图 2.3 Thread类的方法 3. Java实现线程程序 3.1 java.lang.Runnable接口 3.2 实现接口的好处 4. 线程安全 4.1 售票例子 4.2 同步代码块 4.3 同…

大学生活题解

样例输入&#xff1a; 3 .xA ... Bx.样例输出&#xff1a; 6思路分析&#xff1a; 这道题只需要在正常的广搜模板上多维护一个— —方向&#xff0c;如果当前改变方向&#xff0c;就坐标不变&#xff0c;方向变&#xff0c;步数加一&#xff1b;否则坐标变&#xff0c;方向不…