当前位置: 首页 > article >正文

C++第九讲:模板进阶

C++第九讲:模板进阶

  • 1.非类型模板参数
  • 2.模板的特化
  • 3.类模板的特化
    • 3.1全特化
    • 3.2偏特化
      • 3.2.1将模板参数表中的一部分参数特化
      • 3.2.2参数进一步的限制
  • 4.模板分离编译
    • 4.1什么是分离编译
    • 4.2为什么模板类不能够实现分离编译
  • 5.模板总结

1.非类型模板参数

我们平时定义的模板参数都是类型模板参数,而非类型模板参数值的是整形常量,在C++20标准中,也支持了浮点数的定义:

//非类型模板参数
//比如说我们要定义一个静态的栈:
template<class T, size_t N = 10>
//template<class T, double N = 10>//err:常量表达式不是整形
//template<class T, char N = 10>
class Stack
{
private:
	T _a[N];
	int top;
};

int main()
{
	Stack<int, 20> st1;
	Stack<int> st2;
	Stack<int, 100> st3;

	return 0;
}

比如说我们昨天看的那个deque中就看到了非类型模板参数的应用
在这里插入图片描述
C++11也新加了一个array的东西,这个array是一个静态数组,我们看下面:
在这里插入图片描述

2.模板的特化

//我们实现了一个很简单的比较函数模板
template<class T>
bool Less1(T left, T right)
{
	return left < right;
}

int main()
{
	cout << Less1(1, 2) << endl;//可以正常比较

	Date d1(2023, 10, 11);
	Date d2(2023, 12, 11);
	cout << Less1(d1, d2) << endl;//可以正常比较

	return 0;
}

但是,我们这样改一下:

int main()
{
	cout << Less1(1, 2) << endl;//可以正常比较

	Date d1(2023, 10, 11);
	Date d2(2023, 12, 11);
	cout << Less1(d1, d2) << endl;//可以正常比较

	Date* p1 = new Date(2024, 10, 11);
	Date* p2 = new Date(2024, 12, 11);
	cout << Less1(p1, p2) << endl;

	return 0;
}

可以看出,这就成了比较地址了,就没有正确性可言了,所以我们要使用模板的特化来解决这个问题:

//我们实现了一个很简单的比较函数模板
template<class T>
bool Less1(T left, T right)
{
	return left < right;
}

//模板的特化
template<>
bool Less1<Date*>(Date* d1, Date* d2)
{
	return *d1 < *d2;
}

int main()
{
	cout << Less1(1, 2) << endl;//可以正常比较

	Date d1(2023, 10, 11);
	Date d2(2023, 12, 11);
	cout << Less1(d1, d2) << endl;//可以正常比较

	Date* p1 = new Date(2024, 10, 11);
	Date* p2 = new Date(2024, 12, 11);
	cout << Less1(p1, p2) << endl;

	return 0;
}

但是特化有一个比较麻烦的点:

//我们实现了一个很简单的比较函数模板
template<class T>
bool Less1(const T& left, const T& right)
{
	return left < right;
}

//模板的特化
template<>
bool Less1<Date*>(Date* d1, Date* d2)//err:不是函数模板的专用化
{
	return *d1 < *d2;
}

当我们Less1的实现参数为const &类型时,会发生报错,因为特化要保持和模板的性质类似,那么我们可能会这样写:

//模板的特化
template<>
bool Less1<Date*>(const Date*& d1, const Date*& d2)//err:不是函数模板的专用化
{
	return *d1 < *d2;
}

还是不对,因为const Date*& d1中的const修饰的是*d1,而模板参数中的const修饰的是left本身,所以我们要将const改一个位置:

//模板的特化
template<>
bool Less1<Date*>(Date* const& d1, Date* const& d2)//err:不是函数模板的专用化
{
	return *d1 < *d2;
}

3.类模板的特化

3.1全特化

如果我们将模板参数全部都特化的话,就叫做全特化:

template<class T1, class T2>
class Date
{
public:
	Date() { cout << "Date<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

//全特化
template<>
class Date<int, char>
{
public:
	Date() { cout << "Date<int, char>" << endl; }
private:
	int _d1;
	char _d2;
};
int main()
{
	Date<int, int> d1;//Date<T1, T2>
	Date<int, char> d2;//Date<int, char>

	return 0;
}

3.2偏特化

偏特化就是特化部分参数,有两种:

3.2.1将模板参数表中的一部分参数特化

//将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};

3.2.2参数进一步的限制

偏特化不仅仅是指特化部分参数,还可以是对参数的限制:

//两个参数偏特化为指针类型 
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
//两个参数偏特化为引用类型
template <typename T1, typename 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 test2()
{
	Data<double, int> d1;//调用特化的int版本
	Data<int, double> d2;//调用基础的模板
	Data<int*, int*> d3;//调用特化的指针版本
	Data<int&, int&> d4(1, 2);//调用特化的指针版本
}

4.模板分离编译

4.1什么是分离编译

我们在实现之前的类之前,都是按照声明和定义分离分离来实现的,但是模板类的实现时,会有问题,我们下面来看一下模板类实现问题的原因

4.2为什么模板类不能够实现分离编译

在这里插入图片描述

5.模板总结

在这里插入图片描述


http://www.kler.cn/a/373244.html

相关文章:

  • Tomcat 和 Docker部署Java项目的区别
  • 什么是目标检测?
  • 14. NSWindow 窗口与 NSWindowController 窗口控制器
  • 使用 Axios 上传大文件分片上传
  • Jenkins 发布 Java 项目:高效持续集成与部署
  • 多线程显示 CSV 2 PNG 倒计时循环播放
  • 第三方软件检测公司分享:软件性能测试有哪些好用的测试工具?
  • 机器人技术基础(4章逆运动解算和雅克比矩阵)
  • wsl 使用docker 部署oracle11g数据库
  • IDEA集成JProfiler
  • 【已解决,含泪总结】非root权限在服务器Ubuntu18.04上配置python和torch环境,代码最终成功训练(二)
  • SpringBoot利用InitializingBean实现策略模式
  • 一:Linux学习笔记(第一阶段)-- 安装软件 vmware workstation 虚拟机软件 centos系统
  • XQT_UI 组件|01|颜色
  • Vue.js 构建可复用的组件
  • 小型语言模型(LLM)综述!
  • TVB被嘲讽工资低,张兆辉得体且高情商的回应,赢得网友赞赏
  • 【JIT/极态云】技术文档--发起申请
  • Chrome DevTools:Console Performance 汇总篇
  • LabVIEW涡扇发动机加力泵测试
  • 知难而进:什么是Web开发——关于软件开发你需要知道些什么
  • AIGC时代的数据盛宴:R语言引领数据分析新风尚
  • C++算法第五天
  • 无人机产校融合,突破理论与实战代沟,快速转化市场价值
  • php解密,sg11解密-sg15解密 如何由sourceGuardian11-sourceGuardian15加密(sg11加密~sg15加密)的源码
  • Flutter主题切换