C++語法系列之模板進階


前言

本次會介紹一下非類型模板參數、模板的特化(特例化)和模板的可變參數,不是最開始學的模板


一、非類型模板參數

字面意思,比如:

template<size_t N = 10>
或者
template<class T,size_t N = 10>

比如:靜態棧就可以用到,并且由于變長數組的原因,這樣可以更好的使用

template<typename T,size_t N = 10>
class Stack {
private:T a[N];int _top;
};
int main()
{Stack<int> s1;Stack<double, 20> s2;return 0;
}

二、模板的特化

模板的特化是C++98中提出的,他處理一種什么情況呢?就是比如說我想對這個模板是int的類型是進行不一樣的操作,其余都一樣,就用上了模板的特化,
1.非類模板的特化

template<typename T>
void func(T a)
{cout << "void func(T a)" << endl;
}
template<>
void func<int>(int a)
{cout << "void func<int>(int a)" << endl;
}
int main()
{func(double());func(int());return 0;
}

通過這個來看要求:需要有一個主模板,不然會報錯,<>中不寫內容,函數名后加<>,里面寫類型,形參與主模板的對應。
如果還有重載的int優先走哪個?當然是重載的然后是模板的
在這里插入圖片描述
2.類模板的特化
規則與上面類似,但是現在是類名后加<>,里面放類型

template<typename T>
class A {
public:A() {cout << "class A " << endl;}
};
template<>
class A<double> {
public:double a;A() {cout << "class A<double> " << endl;}
};int main()
{A<int> a;A<double> b;return 0;
}

三、全、偏、部分特化

類模板的特化里面呢又搞了幾個東西,偏特化,全特化,部分特化
我這里就用大白話講了,讓大家能夠理解
全特化就是所有的類型全部具體,偏就是全不具體,部分就是一部分具體,上代碼理解一下
全特化:(非類模板只支持全特化,想寫其他的可以去玩重載)

template<typename T>
class A {
public:A() {cout << "class A " << endl;}
};
template<>
class A<double> {
public:A() {cout << "class A<double> " << endl;}
};
template<>
class A<char> {
public:A() {cout << "class A<char> " << endl;}
};
int main()
{A<int> a;A<double> b;A<char>c;return 0;
}

在這里插入圖片描述
偏特化:比如我就想對所有的指針類型進行特殊處理,所有的指針類型也寫不過來,所以這里用上了偏特化


template<typename T>
class A {
public:A() {cout << "class A " << endl;}
};
template<typename T>
class A<T*> {
public:A() {cout << "class A<T*> " << endl;}
};
template<typename T>
class A<T(*)(int,int)> {
public:A() {cout << "class A < T(*)(int, int)>" << endl;}
};
int main()
{A<int> a;A<double*>b;A<int*>c;A<void(*)(int, int)> d;A<int(*)(int, int)> e;return 0;
}

在這里插入圖片描述
部分特化,參考全特化和偏特化,就是一部分顯示出來,一部分不顯示

template<typename T,typename G>
class A {
public:A() {cout << "class A" << endl;}
};
template<typename T>
class A<T*,int> {
public:A() {cout << "class A<T*,int> " << endl;}
};
int main()
{A<int, int> a;A<int*, int> b;A<double*, int> c;return 0;
}

在這里插入圖片描述
沒啥意思,感覺用處也不大

四、模板的可變參數

這里就是C++11搞出來的了
最開始學的能夠接受任意個參數的函數也是C語言用到最多的就是printf和scanf,注意:這里的實現用的并不是模板的可變參數,因為那個時候還沒有C++11(doge,他們是通過宏來實現的奧。
C++里用這個的例子
在這里插入圖片描述
tuple是元組奧,可能你們沒見過,后面在STL里面會講,也是C++11搞出來的東西
在這里插入圖片描述
emplace_back也是后面要提到的,先留個底
一個可變參數模板就是一個可接受可變數目參數的模板函數或者模板類,可變數目的參數稱為參數包,存在兩種參數包:模板參數包,表示零個或者多個模板參數,函數參數包,表示零個或者多個參數
先看寫法

template<typename T,typename... Args>
void foo(const T& t,const Args&... rest)

//Args是一個模板參數包,rest是一個函數參數包,均表示0個或者多個函數參數
編譯器從函數的實參推斷模板參數類型,對于一個可變參數模板,編譯器還會推斷包中參數的數目
當我們要知道包里面有多少元素時,可以使用sizeof…運算符,類似sizeof,也返回一個常量表達式

template<class T,class...Args>
void print(T value,Args...args)
{cout << sizeof...(args) << endl;
}
int main() {print(1, 2,4,4);print(1);print(1, 2, 3, 4,"xxxxxxxx");return 0;
}

在這里插入圖片描述

五、編寫可變參數函數模板

可變參數函數通常是遞歸的,第一步調用處理包中的第一個實參,然后用剩余實參調用自身,所以這里需要兩個參數,比如:

template<class T>
void print(T val)
{cout << val << endl;
}
template<class T,class...Args>
void print(T val, Args...args)
{cout << val << ' ';print(args...);
}

在這里插入圖片描述
當包里剩一個參數的時候就會調用上面的print(),否則就遞歸自身
這樣是不有一個問題啊,我無法print()什么也不傳
可以再分裝一個函數,然后將第一個函數改成無參,這樣當遞歸到參數包沒有參數就會調用那個函數

void _print()
{cout << endl;
}
template<class T,class...Args>
void _print(T val, Args...args)
{cout << val << ' ';_print(args...);
}
template<class...Args>
void print(Args...args)
{_print(args...);
}
int main()
{print(1, 2);print(1, 2,"xxxxxxxxxx");print(1);print();return 0;
}

Warning:當定義可變參數的print時,非可變參數的版本的聲明必須在作用域中,不然會無限的去遞歸。

六、逗號表達式展開參數包

這種不需要遞歸來實現,是直接在函數體中展開的,

template<class T>
void _print(T val)
{cout << val << ' ';
}
template<class ...Args>
void print(Args... args)
{int arr[] = { (_print(args),0)...};cout << endl;
}
int main()
{print(1, 2);print(1, 2,"xxxxxxxxxx");print(1);return 0;
}

這里了解一下就行,至于為什么用逗號表達式,因為這是int類型的數組,而_print返回值是void,所以扔個0就行,建議記下來也沒啥用

template<class T>
int _print(T val)
{cout << val << ' ';return 1;
}
template<class ...Args>
void print(Args... args)
{//int arr[] = { (_print(args),0)...};int arr[] = { _print(args)... };cout << endl;
}

七、轉發參數包

實際上就是玩forward
在這里插入圖片描述

八、emplace_back

剛才看了庫里的實現,既然是模板的可變參數,說明就可以這么玩

int main()
{vector<pair<int, int>> v;v.emplace_back(1, 2);v.push_back(1, 2);//error,push_back不可以這么玩return 0;
}

為什么emplace_back支持這么玩?
在這里插入圖片描述
//別忘了Args&&…args這個不是右值引用,是萬能引用
看第一行,“這個新元素是使用args作為其構造函數的參數就地構造的”相當于直接在容器里面構造,
而push_back是構造 + 移動構造
性能上沒有差很多,因為有了移動構造的緣故,這一步的開銷不是很大
想具體玩差別可以找我上一期的myspace::string,自己調用一下。

總結

這集意義不大,模板的可變參數用的也不多,了解了解就行,emplace_back還是很有用的。明天更新C++11,這個東西巨多,《C++ Primer》第五版這本書上描述了巨多新特性,我會通讀一下然后講一下有用的。模板的可變參數和右值都是C++11里面的,已經繞過了這座大山。

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

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

相關文章

html5的響應式布局的方法示例詳解

以下是HTML5實現響應式布局的5種核心方法及代碼示例: 1. 媒體查詢(核心方案) /* 默認樣式(移動優先) */ .container {padding: 15px; }/* 中等屏幕(平板) */ @media (min-width: 768px) {.container {padding: 30px;max-width: 720px;} }/* 大屏幕(桌面) */ @media …

數字化轉型進階:精讀41頁華為數字化轉型實踐【附全文閱讀】

該文檔聚焦華為數字化轉型實踐&#xff0c;核心內容如下&#xff1a; 轉型本質與目標&#xff1a;數字化轉型是通過數字技術穿透業務&#xff0c;實現物理世界與數字世界的融合&#xff0c;目標是支撐主業成功、提升體驗與效率、探索模式創新。華為以 “平臺 服務” 為核心&am…

C++ - STL #什么是STL #STL的版本 #閉源開源 #STL的六大組件

文章目錄 前言 一、什么是STL 二、STL的版本 1、原始版本 2、P.J.版本 3、RW版本 4、SGI版本 三、閉源、開源 四、STL的六大組件 總結 前言 路漫漫其修遠兮&#xff0c;吾將上下而求索&#xff1b; 一、什么是STL STL(standard template libaray 標準模板庫)&#…

智慧康養護理:科技重塑老齡化社會的健康守護體系

在我國邁入深度老齡化社會的背景下&#xff0c;智慧康養護理作為融合科技與人文的創新模式&#xff0c;正成為提升老年人生活質量、減輕家庭照護壓力、促進健康老齡化的重要路徑。我們將從核心概念、關鍵技術、實際應用與未來趨勢四個維度&#xff0c;為您呈現智慧康養護理的全…

權威認證與質量保障:第三方檢測在科技成果鑒定測試中的核心作用

科技成果鑒定測試是衡量科研成果技術價值與應用潛力的關鍵環節&#xff0c;其核心目標在于通過科學驗證確保成果的可靠性、創新性和市場適配性。第三方檢測機構憑借其獨立性、專業性和權威性&#xff0c;成為科技成果鑒定測試的核心支撐主體。本文從測試流程、第三方檢測的價值…

Linux.docker.k8s基礎概念

1.Linux基本命令 cat 查看文件內容。 cd 進入目標目錄。 ll 查詢當前路勁下文件的詳細信息。 ls 查詢當前路勁下的文件。 touch 建立一個文件。 mkdir 建立一個文件夾。 rm 刪除文件或者目錄。 mv 移動目錄和重新命名文件。 unzip 解壓。 top 查看當前線程的信息。 find …

Python小白的蛻變之旅:從環境搭建到代碼規范(1/10)

摘要&#xff1a;全文圍繞 Python 編程展開&#xff0c;先是介紹如何搭建 Python 開發環境&#xff0c;推薦使用 Anaconda 和 VSCode&#xff0c;并詳細說明了二者的安裝及配置步驟&#xff0c;包括安裝 Anaconda、安裝 VSCode 并配置 Python 插件、選擇 Anaconda 的 Python 解…

linux 1.0.7

用戶和權限的含義與作用 linux中的用戶和文件 用戶的權限是非常重要的 而且有些程序需要使用管理員身份去執行 這些都是非常重要的 不可能讓所有的人擁有所有的權限 這樣的工具可以避免非法的手段來修改計算機中的數據 linux之所以安全還是權限管理做的很棒 每個登錄的用戶都有…

【第4章 圖像與視頻】4.6 結合剪輯區域來繪制圖像

文章目錄 前言示例 前言 本節將綜合運用圖像處理、離屏 canvas 以及剪輯區域等技術實現墨鏡效果。 示例 主線程代碼&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&qu…

UV 包管理工具:替代 pip 的現代化解決方案

安裝 方法一&#xff1a;使用安裝腳本 # macOS 和 Linux curl -LsSf https://astral.sh/uv/install.sh | sh# Windows PowerShell powershell -c "irm https://astral.sh/uv/install.ps1 | iex" 方法二&#xff1a;使用包管理器 # macOS (Homebrew) brew install uv#…

Java注解規范與使用詳解

注解中的空值限制 在Java注解中,元素值不允許使用null引用。這是注解使用中的一項重要約束規則,違反該規則將導致編譯錯誤。需要注意的是,雖然禁止使用null值,但允許為String類型元素指定空字符串(“”),為數組類型元素指定空數組({})。 空值約束示例 以下兩種注解用法…

從零開始的數據結構教程(八)位運算與狀態壓縮

&#x1f3a9; 標題一&#xff1a;位運算基礎——魔術師的二進制手套 位運算是一種直接操作數字二進制位的運算方式&#xff0c;它高效且巧妙&#xff0c;就像魔術師戴上了二進制手套&#xff0c;能夠精準地操控每一個比特。理解位運算是深入學習狀態壓縮和其他底層優化技巧的…

GraalVM加持下的Quarkus極速啟動

1. 引言 1.1 Quarkus與云原生時代的挑戰 隨著云原生架構的普及,傳統Java應用在部署效率、資源消耗和冷啟動性能方面逐漸暴露出短板。Spring Boot等框架雖然功能強大,但在Serverless、邊緣計算等場景下表現乏力。 Quarkus 是 Red Hat 推出的一個專為云原生設計的 Java/Kotl…

vue3 el-input type=“textarea“ 字體樣式 及高度設置

在Vue 3中&#xff0c;如果你使用的是Element Plus庫中的<el-input>組件作為文本域&#xff08;type"textarea"&#xff09;&#xff0c;你可以通過幾種方式來設置字體樣式和高度。 1. 直接在<el-input>組件上使用style屬性 你可以直接在<el-input&…

Matlab中gcb、gcbh、gcs的區別

gcb&#xff1a;返回當前選中模塊的完整路徑名&#xff08;字符串&#xff09; gcbh&#xff1a;返回當前選中模塊的句柄&#xff08;數值標識符&#xff09; gcs&#xff1a;返回當前打開或選中的子系統或頂層模型路徑&#xff08;字符串&#xff09;

大語言模型的技術原理與應用前景:從Transformer到ChatGPT

目錄 摘要 1. 引言 2. Transformer架構核心原理 2.1 自注意力機制 2.2 位置編碼 2.3 前饋神經網絡 3. 從GPT到ChatGPT的演進 3.1 GPT系列模型架構 3.2 訓練流程優化 4. 應用場景與案例分析 4.1 代碼生成 4.2 文本摘要 4.3 問答系統 5. 挑戰與未來方向 5.1 當前技…

Flink Table API 編程入門實踐

Flink Table API 編程入門實踐 前言 Apache Flink 是目前大數據實時計算領域的明星產品&#xff0c;Flink Table API 則為開發者提供了聲明式、類似 SQL 的數據處理能力&#xff0c;兼具 SQL 的易用性與編程 API 的靈活性。本文將帶你快速了解 Flink Table API 的基本用法&am…

Android之ListView

1&#xff1a;簡單列表(ArrayAdapter) 1&#xff1a;運行的結果&#xff1a; 2&#xff1a;首先在MyListView里面創建一個按鈕&#xff0c;點擊的時候進行跳轉。 這里讓我吃驚的是&#xff0c;Button里面可以直接設置onClick .java里面的方法。 也即是點擊這個按鈕之后就會去…

Python(十四)

1.type函數和init_subclass_ init_subclass_ 2.元類 類就是用來創建對象的模版&#xff0c;類是由type創造而來的&#xff0c;元類就是創建類的模版&#xff0c;type可以用來創造類&#xff0c;因為type本身就是一個元類&#xff0c;使用元類來創造類&#xff0c;元類之間也有…

當前用戶的Git全局配置情況:git config --global --list

通過config命令可以查詢當前用戶的全局配置情況。這些配置項定義了 Git 在全局范圍內的行為&#xff0c;包括如何處理大文件、SSL 證書驗證以及提交時的用戶信息。 git config --global --list http.sslVerifyfalse 這個配置項禁用了 SSL 證書驗證。這在與自簽名證書的 Git 服…