C++模板知識

目錄

引言?

一、非類型模板參數

二、類模板的特化?

(一)概念?

(二)函數模板特化?

(三)類模板特化?

1. 全特化?

2. 偏特化?

(四)類模板特化應用示例?

三、模板的分離編譯?

(一)什么是分離編譯?

(二)模板的分離編譯?

(三)解決方法?

四、模板總結?

(一)優點?

(二)缺陷?


引言

在C++編程世界里,模板是一項極為強大且靈活的特性,它能讓我們編寫出通用、可復用的代碼。今天,就讓我們深入探究C++模板的幾個關鍵方面:非類型模板參數、類模板的特化以及模板的分離編譯。
?

一、非類型模板參數

模板參數分為類型形參與非類型形參。類型形參,我們常見于模板參數列表中,通常緊跟在?class?或者?typename?之后。而非類型模板參數則別具一格,它使用一個常量作為類(函數)模板的一個參數,在模板中可當作常量使用。
?
代碼示例
?

cpp ??
namespace bite {// 定義一個模板類型的靜態數組template<class T, size_t N = 10>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];size_t _size;};
}


?注意事項
?
1.?浮點數、類對象以及字符串是不允許作為非類型模板參數的,用整形初始化
?
2.?非類型的模板參數必須在編譯期就能確認結果。
?

二、類模板的特化
?

(一)概念
?

模板能實現與類型無關的代碼,但遇到特殊類型時,可能會產生錯誤結果,這就需要對模板進行特化。特化即在原模板類基礎上,針對特殊類型進行特殊化的實現方式。模板特化主要分為函數模板特化與類模板特化。
?

(二)函數模板特化
?

特化步驟
?
1.?首先得有一個基礎的函數模板。
?
2.?使用關鍵字?template?后跟一對空的尖括號?<>?。
?
3.?函數名后緊跟一對尖括號,在尖括號中指定需要特化的類型。
?
4.?函數形參表必須要和模板函數的基礎參數類型完全相同,否則不同編譯器可能會報奇怪錯誤。


代碼示例
?

cpp ??
// 函數模板 -- 參數匹配
template<class T>
bool Less(T left, T right) {return left < right;
}// 對Less函數模板進行特化
template<>
bool Less<Date*>(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;
}


?
一般情況下,如果函數模板遇到不能處理或者處理有誤的類型,為實現簡單,通常直接給出特化版本。函數模板不建議過度特化,因為直接編寫普通函數實現簡單明了,代碼可讀性高。
?

(三)類模板特化
?

1. 全特化
?

全特化即將模板參數列表中所有的參數都確定化。
?

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


?

2. 偏特化
?

偏特化是針對模板參數進一步進行條件限制設計的特化版本,主要有以下兩種表現方式:
?
- 部分特化:將模板參數類表中的一部分參數特化。
?

cpp ??
// 將第二個參數特化為int
template <class T1>
class Data<T1, int> {
public:Data() { cout << "Data<T1, int>" << endl; }
private:T1 _d1;int _d2;
};


?
?
- 參數更進一步的限制:不僅特化部分參數,還針對模板參數做更進一步的條件限制。
?

cpp ??
// 兩個參數偏特化為指針類型
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;
};


?

(四)類模板特化應用示例
?


以按照小于比較的類模板?Less?為例:
?

cpp ??
#include<vector>
#include <algorithm>template<class T>
struct Less {bool operator()(const T& x, const T& y) const {return x < y;}
};int main() {Date d1(2022, 7, 7);Date d2(2022, 7, 6);Date d3(2022, 7, 8);vector<Date> v1;v1.push_back(d1);v1.push_back(d2);v1.push_back(d3);// 可以直接排序,結果是日期升序sort(v1.begin(), v1.end(), Less<Date>());vector<Date*> v2;v2.push_back(&d1);v2.push_back(&d2);v2.push_back(&d3);// 此處直接排序結果錯誤,因為sort最終按照Less模板中方式比較,只會比較指針,而非指針指向內容// 此時需要特化Less類模板來處理sort(v2.begin(), v2.end(), Less<Date*>());return 0;
}// 對Less類模板按照指針方式特化
template<>
struct Less<Date*> {bool operator()(Date* x, Date* y) const {return *x < *y;}
};


?

三、模板的分離編譯
?

(一)什么是分離編譯
?


一個程序(項目)由若干個源文件共同實現,每個源文件單獨編譯生成目標文件,最后將所有目標文件鏈接起來形成單一的可執行文件,這種模式就是分離編譯模式。
?


(二)模板的分離編譯
?


當模板的聲明與定義分離開,在頭文件中聲明,源文件中定義時,會出現問題。例如:
a.h
?

cpp ??
template<class T>
T Add(const T& left, const T& right);a.cppcpp ??
template<class T>
T Add(const T& left, const T& right) {return left + right;
}main.cppcpp ??
#include "a.h"
int main() {Add(1, 2);Add(1.0, 2.0);return 0;
}


?
在這種情況下,?a.cpp?中編譯器沒看到對?Add?模板函數的實例化,不會生成具體的加法函數;?main.cpp?編譯后在鏈接時找不到?Add<int>?與?Add<double>?的具體代碼,就會報錯。
?

(三)解決方法
?


1.?將聲明和定義放到一個文件“xxx.hpp”里或者?xxx.h?也可以,推薦這種方式。
?
2.?模板定義的位置顯式實例化,但這種方法不實用,不推薦。

?

cpp ??
template<class T>
T Add(const T& left, const T& right);a.cppcpp ??
template<class T>
T Add(const T& left, const T& right) 
{return left + right;
}//?template
//int Add(const int& left, const int& right) 
//?template
//double Add(const double& left, const double& right) main.cppcpp ??
#include "a.h"
int main() 
{Add(1, 2);Add(1.0, 2.0);return 0;
}


四、模板總結
?

(一)優點
?


1.?模板復用了代碼,節省資源,能實現更快的迭代開發,C++的標準模板庫(STL)就是基于模板產生的。
?
2.?增強了代碼的靈活性,能適應多種數據類型。
?


(二)缺陷
?

1.?模板會導致代碼膨脹問題,編譯時會針對不同類型實例化出多份代碼,也會使編譯時間變長。
?
2.?出現模板編譯錯誤時,錯誤信息非常凌亂,難以定位錯誤根源。
?
希望通過這篇博客,大家能對C++模板有更深入、全面的理解,在今后的編程中能更好地運用模板特性編寫出高質量、可復用的代碼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79413.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79413.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79413.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pillow 移除或更改了 FreeTypeFont.getsize() 方法

w, h self.font.getsize(label) # text width, height AttributeError: FreeTypeFont object has no attribute getsize 在Pillow 項目的變更日志里可以查到哪個版本移除了 getsize() 方法&#xff0c;Pillow倉庫&#xff1a; Releases python-pillow/Pillow GitHub 因為…

Matlab自學筆記

一、我下載的是Matlab R2016a軟件&#xff0c;打開界面如下&#xff1a; 二、如何調整字體大小&#xff0c;路徑為&#xff1a;“主頁”->“預設”->“字體”。 三、命令行窗口是直接進行交互式的&#xff0c;如下輸入“3 5”&#xff0c;回車&#xff0c;就得到結果“…

VR汽車線束:汽車制造的新變革

汽車線束&#xff0c;作為汽車電路網絡的主體&#xff0c;宛如汽車的 “神經網絡”&#xff0c;承擔著連接汽車各個部件、傳輸電力與信號的重任&#xff0c;對汽車的正常運行起著關鍵作用。從汽車的發動機到儀表盤&#xff0c;從傳感器到各類電子設備&#xff0c;無一不是通過線…

目標檢測YOLO實戰應用案例100講-基于多級特征融合的小目標深度檢測網絡

目錄 知識儲備 基于多級特征融合的小目標深度檢測網絡實現 一、環境配置 二、核心代碼實現 1. 多級特征融合模塊(models/fpn.py ) 2. 主干網絡(models/backbone.py ) 3. 檢測頭(models/detector.py ) 三、完整網絡架構(models/net.py ) 四、訓練代碼(train.p…

【云原生】基于Centos7 搭建Redis 6.2 操作實戰詳解

目錄 一、前言 二、Redis 6.2 安裝過程 2.1 下載安裝包 2.2 安裝包解壓 2.3 安裝包編譯 2.3 安裝 2.4 啟動redis 2.4.1 前臺啟動&#xff08;不推薦&#xff09; 2.4.2 后啟動&#xff08;推薦&#xff09; 2.4.3 關閉redis服務 2.4.4 設置客戶端連接 三、寫在最后 …

云計算-容器云-服務網格

服務網格:創建VirtualService(3分) ? 將Bookinfo應用部署到default命名空間下,為Bookinfo應用創建一個名為reviews的VirtualService,要求來自名為Jason的用戶的所有流量將被路由到reviews服務的v2版本。(需要用到的軟件包:ServiceMesh.tar.gz) # 上傳解壓 tar -xf Se…

【Res模塊學習】結合CIFAR-100分類任務學習

初次嘗試訓練CIFAR-100&#xff1a;【圖像分類】CIFAR-100圖像分類任務-CSDN博客 1.訓練模型&#xff08;MyModel.py&#xff09; import torch import torch.nn as nnclass BasicRes(nn.Module):def __init__(self, in_cha, out_cha, stride1, resTrue):super(BasicRes, sel…

愛勝品ICSP YPS-1133DN Plus黑白激光打印機報“自動進紙盒進紙失敗”處理方法之一

故障現象如下圖提示&#xff1a; 用戶的愛勝品ICSP YPS-1133DN Plus黑白激光打印機在工作過程中提示自動進紙盒進紙失敗并且紅色故障燈閃爍&#xff1b; 給出常見故障一般處理建議如下&#xff1a; 當您的愛勝品ICSP YPS-1133DN Plus 黑白激光打印機出現“自動進紙盒進紙失敗”…

Flinkcdc 實現 MySQL 寫入 Doris

Flinkcdc 實現 MySQL 寫入 Doris Flinkcdc 實現 MySQL 寫入 Doris 一、環境配置 Doris&#xff1a;3.0.4 JDK 17 MySQL &#xff08;業務數據庫&#xff09;&#xff1a;5.7 MySQL&#xff08;本地數據庫&#xff09;&#xff1a;5.7 Flink&#xff1a;flink-1.19.1 flinkc…

【Linux庖丁解牛】—環境變量!

目錄 1. 環境變量 1.1 概念介紹 1.2 命令行參數 1.3 一個例子&#xff0c;一個環境變量 1.4 認識更多的環境變量 1.5 獲取環境變量的方法 a. 指令操作 b. 代碼操作 1.6 理解環境變量的特性 a.環境變量具有全局特性 b.補充兩個概念(為后面埋一個伏筆) 1. 環境變量 …

LangChain4j +DeepSeek大模型應用開發——7 項目實戰 創建硅谷小鹿

這部分我們實現硅谷小鹿的基本聊天功能&#xff0c;包含聊天記憶、聊天記憶持久化、提示詞 1. 創建硅谷小鹿 創建XiaoLuAgent package com.ai.langchain4j.assistant;import dev.langchain4j.service.*; import dev.langchain4j.service.spring.AiService;import static dev…

普通 html 項目也可以支持 scss_sass

項目結構示例 下載vscode的插件Live Sass Compiler 自動監聽編譯scss 下載插件Live Server 用于 web 服務器&#xff0c;打開 html 文件到瀏覽器&#xff0c;也可以不用這個&#xff0c;自己用 nginx 或者寶塔其他 web 工具 新建一個 index.scss打開&#xff0c;點擊 vscode 底…

網工_IP協議

2025.02.17&#xff1a;小猿網&網工老姜學習筆記 第19節 IP協議 9.1 IP數據包的格式&#xff08;首部數據部分&#xff09;9.1.1 IP協議的首部格式&#xff08;固定部分可變部分&#xff09; 9.2 IP數據包分片&#xff08;找題練&#xff09;9.3 TTL生存時間的應用9.4 常見…

SQL語句練習 自學SQL網 在查詢中使用表達式 統計

目錄 Day 9 在查詢中使用表達式 Day 10 在查詢中進行統計 聚合函數 Day 11 在查詢中進行統計 HAVING關鍵字 Day12 查詢執行順序 Day 9 在查詢中使用表達式 SELECT id , Title , (International_salesDomestic_sales)/1000000 AS International_sales FROM moviesLEFT JOIN …

基于機器學習的輿情分析算法研究

標題:基于機器學習的輿情分析算法研究 內容:1.摘要 隨著互聯網的飛速發展&#xff0c;輿情信息呈現爆炸式增長&#xff0c;如何快速準確地分析輿情成為重要課題。本文旨在研究基于機器學習的輿情分析算法&#xff0c;以提高輿情分析的效率和準確性。方法上&#xff0c;收集了近…

菲索旋轉齒輪法:首次地面光速測量的科學魔術

一、當齒輪邂逅光束&#xff1a;19世紀的光速實驗室 1849年&#xff0c;法國物理學家阿曼德菲索&#xff08;Armand Fizeau&#xff09;在巴黎郊外的一座莊園里&#xff0c;用一組旋轉齒輪、一面鏡子和一盞油燈&#xff0c;完成了人類首次地面光速測量。他的實驗測得光速為315…

上位機知識篇---PSRAM和RAM

文章目錄 前言一、RAM&#xff08;Random Access Memory&#xff09;1. 核心定義分類&#xff1a;SRAM&#xff08;靜態RAM&#xff09;DRAM&#xff08;動態RAM&#xff09; 2. 關鍵特性SRAM優點缺點應用 DRAM優點缺點應用 3. 技術演進DDR SDRAMLPDDR&#xff08;低功耗DRAM&a…

Qt QComboBox 下拉復選多選(multicombobox)

Qt QComboBox 下拉復選多選&#xff08;multicombobox&#xff09;&#xff0c;備忘&#xff0c;待更多測試 【免費】QtQComboBox下拉復選多選&#xff08;multicombobox&#xff09;資源-CSDN文庫

ElasticSearch深入解析(五):如何將一臺電腦上的Elasticsearch服務遷移到另一臺電腦上

文章目錄 0.安裝數據遷移工具1.導出數據2.導出mapping3.導出查詢模板4.拷貝插件5.拷貝配置6.導入到目標電腦上 0.安裝數據遷移工具 Elasticsearch dump是一個用于將Elasticsearch索引數據導出為JSON格式的工具。你可以使用Elasticsearch dump通過命令行或編程接口來導出數據。…

微服務中組件掃描(ComponentScan)的工作原理

微服務中組件掃描(ComponentScan)的工作原理 你的問題涉及到Spring框架中ComponentScan的工作原理以及Maven依賴管理的影響。我來解釋為什么能夠掃描到common模塊的bean而掃描不到其他模塊的bean。 根本原因 關鍵在于**類路徑(Classpath)**的包含情況&#xff1a; Maven依賴…