⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///
WARNING \]: DETECTING HIGH ENERGY
**🌊 🌉 🌊 心手合一 · 水到渠成**

|------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| **\>\>\> ACCESS TERMINAL \<\<\<** ||
| [**\[ 🦾 作者主页 \]**](https://blog.csdn.net/fengtinghuqu520?spm=1000.2115.3001.5343) | [**\[ 🔥 C语言核心 \]**](https://blog.csdn.net/fengtinghuqu520/category_12955956.html) |
| [**\[ 💾 编程百度 \]**](https://blog.csdn.net/fengtinghuqu520/category_13083835.html) | [**\[ 📡 代码仓库 \]**](https://blog.csdn.net/fengtinghuqu520/article/details/147275999?spm=1001.2014.3001.5502) |
---------------------------------------
Running Process: 100% \| Latency: 0ms
*** ** * ** ***
#### 索引与导读
* [1. 非类型模板参数](#1. 非类型模板参数)
*
* [1.1)类型形参](#1.1)类型形参)
* [1.2)非类型形参](#1.2)非类型形参)
* [2. 模板的特化](#2. 模板的特化)
*
* [2.1)函数模板特化](#2.1)函数模板特化)
* [2.2)类模板特化](#2.2)类模板特化)
*
* [2.2.1)全特化](#2.2.1)全特化)
* [2.2.2)偏特化](#2.2.2)偏特化)
* [3. 模板分离编译](#3. 模板分离编译)
* [💻结尾--- 核心连接协议](#💻结尾— 核心连接协议)
> [🔗Lucy的空间骇客裂缝: C++ 模板初阶](https://blog.csdn.net/fengtinghuqu520/article/details/158240822?spm=1011.2415.3001.10575&sharefrom=mp_manage_link)
## 1. 非类型模板参数
### 1.1)类型形参
```cpp
template
T add(T a, T b) {
return a + b;
}
// 使用时:
add(5, 3); // T 被替换为 int
add(1.2, 3.4); // T 被替换为 double
```
*** ** * ** ***
### 1.2)非类型形参
**非类型形参不代表类型,而代表一个常量值**。你可以把它看作是在编译期确定的"常数变量"
```cpp
namespace bite
{
// 定义一个模板类型的静态数组
// T: 类型形参,决定数组存储什么
// N: 非类型形参,决定数组的大小(编译期常量)
template
class array
{
public:
// 下标引用操作符(支持修改)
T& operator[](size_t index) {
return _array[index];
}
// 下标引用操作符(常函数,仅供读取)
const T& operator[](size_t index) const {
return _array[index];
}
// 获取数组大小
size_t size() const {
return _size;
}
// 判空
bool empty() const {
return 0 == _size;
}
private:
T _array[N]; // 利用非类型形参 N 开辟空间
size_t _size = N; // 初始化大小为 N
};
}
```
**╔═█▓▒░ CODE CORE 🔥**
**┌─────────────┐
│ 代码关键点 │`namespace bite`
└─────────────┘**
* **作用:** 定义一个名为 `bite` 的命名空间。
* **目的:** 防止类名 `array` 与标准库中的 `std::array` 产生冲突(即"命名污染")。
**╔═█▓▒░ CODE CORE 🔥**
**┌─────────────┐
│ 代码关键点 │`template`
└─────────────┘**
* **`template`:** 告诉编译器,接下来的代码是一个模板。
* **`class T`:** 类型形参。代表数组要存储的数据类型(如 `int`,`double`)。
* **`size_t N = 10`:** 非类型形参。
* **`size_t`** 是无符号整型,常用于表示大小。
* **`N`** 代表数组的长度。
* **`= 10`** 是缺省值。如果用户不指定大小,默认创建长度为 `10` 的数组
> **注意:**
>
> 1. **浮点数、类对象以及字符串**是不允许作为非类型模板参数的
> 2. **非类型的模板参数**必须在编译期就能确认结果
*** ** * ** ***
## 2. 模板的特化
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板
```cpp
// 函数模板 -- 参数匹配
template
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;
}
```
> **详细代码解析**
>
> * 当你写下 `Less(d1, d2)` 时,编译器并不会直接运行这个函数
> * **类型推导:** 编译器看到`d1`和`d2`的类型是`Date`
> * **生成代码:** 编译器会根据你之前定义的`template`,自动生成一份专门为 `Date` 类型服务的函数代码
> * **生成的底层伪代码:**
>
> ```cpp
> bool Less(Date left, Date right) {
> return left < right;
> }
> ```
> 可以看到,`Less` 绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果
>
> 上述示例中,**`p1` 指向的 `d1` 显然小于 `p2` 指向的 `d2` 对象,但是 `Less` 内部并没有比较 `p1` 和 `p2` 指向的对象内容,而比较的是 `p1` 和 `p2` 指针的地址,这就无法达到预期而错误**
此时,就需要对模板进行特化。
即:**在原模板类的基础上,针对特殊类型所进行特殊化的实现方式**
模板特化中分为**函数模板特化** 和**类模板特化**
*** ** * ** ***
### 2.1)函数模板特化
**函数模板的特化步骤:**
1. **必须要先有一个基础的函数模板**
2. **关键字 `template` 后面接一对空的尖括号 `<>`**
3. 函数名后跟一对**尖括号** ,**尖括号中指定需要特化的类型**
4. **函数形参表:** 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
````cpp
```cpp
// 函数模板 -- 参数匹配
template
bool Less(T left, T right)
{
return left < right;
}
// 对 Less 函数模板进行特化
template<>
bool Less(Date* left, Date* 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;
}
````
**注意:** 一般情况下如果**函数模板遇到不能处理或者处理有误的类型**,为了实现简单通常都是将该函数直接给出。
```cpp
bool Less(Date* left, Date* right)
{
return *left < *right;
}
```
该种实现简单明了,代码的可读性高,容易书写,因为对于一些参数类型复杂的函数模板,特化时特别给出,**因此函数模板不建议特化**
*** ** * ** ***
### 2.2)类模板特化
#### 2.2.1)全特化
全特化是指为模板参数提供一组**具体的类型**。一旦进行了全特化,原来的"模板"就不再具有通用性,而是变成了一个针对特定类型的"具体类"
*** ** * ** ***
**语法特点**
* 必须先声明基础模板。
* **使用 `template <>`** 开头(不带任何参数)。
* 在类名后的角括号中指定具体的类型
```cpp
// 1. 基础模板 (Primary Template)
template
class Storage {
public:
void print() { cout << "通用模板:存储普通数据" << endl; }
};
// 2. 全特化版本:专门处理 char* 类型
template <>
class Storage {
public:
void print() { cout << "全特化模板:专门处理字符串指针" << endl; }
};
```
*** ** * ** ***
#### 2.2.2)偏特化
**偏特化(也叫部分特化)** 是指在不完全确定所有模板参数的情况下,对满足某种特定模式的参数进行定制
**注意:** 只有类模板支持偏特化,函数模板不支持偏特化(只能全特化或通过重载解决)
* **偏特化通常分为两种形式:**
A. 参数个数上的偏特化
当模板有多个参数时,只固定其中的一部分。
```cpp
// 基础模板
template
class Data { };
// 偏特化:将第二个参数固定为 int
template
class Data { };
```
B. 参数范围上的偏特化(模式匹配)
不固定具体的类型,但限制类型的**形态**(例如从 T 缩小为 T\*、T\& 或 vector)
```cpp
// 基础模板
template
class Handler { };
// 偏特化:只处理指针类型
template
class Handler { };
// 偏特化:只处理常量引用类型
template
class Handler { };
```
*** ** * ** ***
## 3. 模板分离编译
**一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程** ------------**分离编译模式**
*** ** * ** ***
假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:
```cpp
// a.h
template
T Add(const T& left, const T& right);
// a.cpp
template
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;
}
```
**代码分析:**
`C/C++` 程序要运行,一般要经历以下步骤:
**预处理** → **编译** → **汇编** → **链接**
* **编译**:对程序按照语言特性进行词法、语法、语义分析,错误检查无误后生成汇编代码。
> **注意:** 头文件不参与编译,编译器对工程中的多个源文件是分离开单独编译的
* **链接** :将多个 `.obj` 文件合并成一个,并处理没有解决的地址问题

*** ** * ** ***
**解决方法:**
1. 将声明和定义放到一个文件 `"xxx.hpp"` 里面或者 `xxx.h` 其实也是可以的。**推荐使用这种**
2. 模板定义的位置显式实例化。这种方法不实用,**不推荐使用**
*** ** * ** ***
## 💻结尾--- 核心连接协议
**警告:** 🌠🌠正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层,请执行以下指令序列以同步数据:🌠🌠
*** ** * ** ***
**【📡】 建立深度链接:** **关注**本终端。在赛博丛林中深耕底层架构,从原始代码到进阶协议,同步见证每一次系统升级。
**【⚡】 能量过载分发:** 执行**点赞**操作。通过高带宽分发,让优质模组在信息流中高亮显示,赋予知识跨维度的传播力。
**【💾】 离线缓存核心:** 将本页加入**收藏**。把这些高频实战逻辑存入你的离线存储器,在遭遇系统崩溃或需要离线检索时,实现瞬时读取。
**【💬】 协议加密解密:** 在**评论区**留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞(那些年踩过的坑),通过交互式编译共同绕过技术陷阱。
**【🛰️】 信号频率投票:** 通过**投票**发射你的选择。你的每一次点击都在重新定义矩阵的进化方向,决定下一个被全量拆解的技术节点。
*** ** * ** ***

