C++模板編程——可變參函數模板

目錄

1. 可變參函數模板基本介紹

2. 參數包展開——通過遞歸函數

3. 參數包展開——通過編譯期間if語句(constexpr if)

4. 重載

5. 后記


進來看的小伙伴們應該對C++中的模板有了一定了解,下面給大家介紹一下可變參函數模板。過于基礎的概念將不仔細介紹。

1. 可變參函數模板基本介紹

先來看一個可變參函數模板的示例:

#include <iostream>using namespace std;template<typename... T>
void myFunc(T... args)
{cout << "----------------MyFunc begin -----------------" << endl;cout << "收到的參數個數:" << sizeof...(args) << endl;cout << "收到的參數類型個數:" << sizeof...(T) << endl;cout << "----------------MyFunc end   -----------------" << endl;
}int main()
{myFunc();myFunc(1);myFunc(1, 2);myFunc(1, 2, 3);
}

運行結果如下圖:

仔細觀察上面給出的代碼,有三點需要注意:

  1. template行中typename后面跟著三個點,然后是類型模板參數T
  2. 在函數簽名行void myFunc(T... args),因為T后面跟著三個點,所以T稱為可變參類型。看起來是一個類型,實際上其代表了0個到多個的類型。?args稱為一包參數,每個參數的類型都可以為任意類型。
  3. 在C++11引入了sizeof...()的語法,這是固定寫法,用于可變參函數模板或可變參模板內部,表示模板參數個數或類型數量。只有這種...的可變參才可以使用。

上面的代碼有一個問題,在拿到了一堆參數args之后,我們需要拿到每一個參數進行處理。這就涉及到了參數包的展開,下面將介紹兩種參數包展開的兩種方法。

2. 參數包展開——通過遞歸函數

參數包展開的套路是比較固定的,通過遞歸函數進行參數包展開是一種經典手法。

為了實現遞歸函數的方式展開參數包,需要編寫一個參數包展開函數和一個同名的遞歸終止函數

這兩個函數一起實現參數包的展開。

先看代碼:

#include <iostream>using namespace std;void myFunc() // 同名的參數包遞歸終止函數
{cout << "參數包展開的遞歸終止函數" << endl;
}template<typename T, typename... U>
void myFunc(T arg1, U... args) // 參數包展開函數
{cout << "收到的參數為:" << arg1 << endl;myFunc(args...);
}int main()
{myFunc(1, 2, 3);
}

運行截圖如下圖所示:

通過代碼可以看到參數包展開函數是一個函數模板。void myFunc(T arg1, U... args);它的函數簽名中,T為1個參數,U為0個或多個參數類型。所以這個函數模板最少需要一個參數

通過代碼可以看到,遞歸終止函數為一個同名的普通的函數(不是函數模板)接收0個參數


在main函數中調用myFunc(1,2,3);時,1會匹配到arg1,2和3會匹配到args。

在myFunc內部會調用myFunc(2,3);,2會匹配到arg1,3會匹配到args。

myFunc內部繼續調用myFunc(3);,3會匹配到arg1,args沒有匹配到任何參數。

接著會調用myFunc(); 調用遞歸終止函數。

通過這種遞歸調用的方式就實現了參數包的展開,這是一種固定的編程手法,理解學會就好了。

3. 參數包展開——通過編譯期間if語句(constexpr if)

在C++17標準中增加了編譯期間if語句。與常規的if語句類似,但是在if語句后增加了一個constexpr關建字,這個關建字代表編譯時求值。

有了編譯期間if語句就非常方便了,不需要編寫遞歸終止函數了。具體看下面的代碼:

#include <iostream>using namespace std;template<typename T, typename ...U>
void myFunc(T arg1, U... args)
{cout << "收到的參數為:" << arg1 << endl;if constexpr (sizeof...(args) > 0){myFunc(args...);}else{cout << "沒有更多參數了" << endl;}
}int main()
{myFunc(1, 2, 3);
}

運行結果如下圖所示:

使用if constexpr和sizeof...()來判斷args中含有的參數個數。當剩余的參數個數大于0時,繼續遞歸調用,否則會執行else分支。

非常好理解,而且編寫起來也非常方便。

需要注意的是,if constexpr所指定的條件必須在編譯期間能夠求值,不可以是變量。

4. 重載

可變參函數模板也可以重載,具體見下面的代碼。

#include <iostream>using namespace std;template<typename... T>
void myFunc(T... args)
{cout << "void myFunc(T... args); 執行了" << endl;
}template<typename... T>
void myFunc(T*... args)
{cout << "void myFunc(T*... args); 執行了" << endl;
}void myFunc(int arg)
{cout << "void myFunc(int arg); 執行了" << endl;
}int main()
{myFunc(1, 2, 3);myFunc((int*)nullptr);myFunc(1);
}

運行截圖如下所示:

5. 后記

可變參函數模板還是比較好理解的,有講得不對的地方敬請批評指正。

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

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

相關文章

ChatGPT-4o和ChatGPT-4o mini的差異點

在人工智能領域&#xff0c;OpenAI再次引領創新潮流&#xff0c;近日正式發布了其最新模型——ChatGPT-4o及其經濟實惠的小型版本ChatGPT-4o Mini。這兩款模型雖同屬于ChatGPT系列&#xff0c;但在性能、應用場景及成本上展現出顯著的差異。本文將通過圖文并茂的方式&#xff0…

三數之和(15)

15. 三數之和 - 力扣&#xff08;LeetCode&#xff09; 可以一起總結的題目&#xff1a;三角形的最大周長&#xff08;976&#xff09;-CSDN博客 解法&#xff1a; class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {vector…

2025最新源支付V7全套開源版+Mac云端+五合一云端

2025最新源支付V7全套開源版Mac云端五合一云端 官方1999元&#xff0c; 最新非網上那種功能不全帶BUG開源版&#xff0c;可以自己增加授權或二開 擁有卓越的性能和豐富的功能。它采用全新輕量化的界面UI&#xff0c;讓您能更方便快捷地解決知識付費和運營贊助的難題 它基于…

9 點結構模塊(point.rs)

一、point.rs源碼 use super::UnknownUnit; use crate::approxeq::ApproxEq; use crate::approxord::{max, min}; use crate::length::Length; use crate::num::*; use crate::scale::Scale; use crate::size::{Size2D, Size3D}; use crate::vector::{vec2, vec3, Vector2D, V…

數據分析系列--[12] RapidMiner辨別分析(含數據集)

一、數據準備 二、導入數據 三、數據預處理 四、建模辨別分析 五、導入測試集進行辨別分析 一、數據準備 點擊下載數據集 二、導入數據 三、數據預處理 四、建模辨別分析 五、導入測試集進行辨別分析 Ending, congratulations, youre done.

Day33【AI思考】-函數求導過程 的優質工具和網站

文章目錄 **函數求導過程** 的優質工具和網站**一、動態圖形工具**1. **Desmos&#xff08;網頁端&#xff09;**2. **GeoGebra&#xff08;全平臺&#xff09;** **二、分步推導工具**3. **Wolfram Alpha&#xff08;網頁/App&#xff09;**4. **Symbolab&#xff08;網頁/App…

個人筆記(很沒營養,純備忘錄)

1.輸入電阻和輸出電阻指在一個可劃分為3部分的電路中&#xff0c;中間部分電路相當于前面電路的負載有輸入端電阻&#xff0c;稱輸入電阻&#xff0c;相對于后面部分等效為電源有輸出端內阻&#xff0c;稱輸出電阻 理所當然的希望輸出電阻對負載影響小&#xff0c;輸入電阻能完…

當卷積神經網絡遇上AI編譯器:TVM自動調優深度解析

從銅線到指令&#xff1a;硬件如何"消化"卷積 在深度學習的世界里&#xff0c;卷積層就像人體中的毛細血管——數量龐大且至關重要。但鮮有人知&#xff0c;一個簡單的3x3卷積在CPU上的執行路徑&#xff0c;堪比北京地鐵線路圖般復雜。 卷積的數學本質 對于輸入張…

51單片機 02 獨立按鍵

一、獨立按鍵控制LED亮滅 輕觸按鍵&#xff1a;相當于是一種電子開關&#xff0c;按下時開關接通&#xff0c;松開時開關斷開&#xff0c;實現原理是通過輕觸按鍵內部的金屬彈片受力彈動來實現接通和斷開。 #include <STC89C5xRC.H> void main() { // P20xFE;while(1){…

系統URL整合系列視頻二(界面原型)

視頻 系統URL整合系列視頻二&#xff08;界面原型&#xff09; 視頻介紹 &#xff08;全國&#xff09;大型分布式系統Web資源URL整合需求界面原型講解。當今社會各行各業對軟件系統的web資源訪問權限控制越來越嚴格&#xff0c;控制粒度也越來越細。安全級別提高的同時也增加…

vscode命令面板輸入 CMake:build不執行提示輸入

CMake&#xff1a;build或rebuild不編譯了&#xff0c;彈出:> [Add a new preset] , 提示輸入發現settings.jsons設置有問題 { "workbench.colorTheme": "Default Light", "cmake.pinnedCommands": [ "workbench.action.tasks.configu…

wax到底是什么意思

在很久很久以前&#xff0c;人類還沒有誕生文字之前&#xff0c;人類就產生了語言&#xff1b;在誕生文字之前&#xff0c;人類就已經使用了語言很久很久。 沒有文字之前&#xff0c;人們的語言其實是相對比較簡單的&#xff0c;因為人類的生產和生活水平非常低下&#xff0c;…

SSRF 漏洞利用 Redis 實戰全解析:原理、攻擊與防范

目錄 前言 SSRF 漏洞深度剖析 Redis&#xff1a;強大的內存數據庫 Redis 產生漏洞的原因 SSRF 漏洞利用 Redis 實戰步驟 準備環境 下載安裝 Redis 配置漏洞環境 啟動 Redis 攻擊機遠程連接 Redis 利用 Redis 寫 Webshell 防范措施 前言 在網絡安全領域&#xff0…

【周易哲學】生辰八字入門講解(八)

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一個正在變禿、變強的文藝傾年。 &#x1f514;本文講解【周易哲學】生辰八字入門講解&#xff0c;期待與你一同探索、學習、進步&#xff0c;一起卷起來叭&#xff01; 目錄 一、六親女命六親星六親宮位相互關系 男命六親星…

CAN總線數據采集與分析

CAN總線數據采集與分析 目錄 CAN總線數據采集與分析1. 引言2. 數據采集2.1 數據采集簡介2.2 數據采集實現3. 數據分析3.1 數據分析簡介3.2 數據分析實現4. 數據可視化4.1 數據可視化簡介4.2 數據可視化實現5. 案例說明5.1 案例1:數據采集實現5.2 案例2:數據分析實現5.3 案例3…

【c++】類與對象詳解

目錄 面向過程思想和面向對象思想類的定義引入類的關鍵字類定義的兩種方式類的訪問限定符類的作用域類大小的計算封裝 this指針類的6個默認成員函數構造函數初步理解構造函數深入理解構造函數初始化列表單參數構造函數引發的隱式類型轉換 析構函數拷貝構造函數賦值運算符重載運…

大模型訓練(5):Zero Redundancy Optimizer(ZeRO零冗余優化器)

0 英文縮寫 Large Language Model&#xff08;LLM&#xff09;大型語言模型Data Parallelism&#xff08;DP&#xff09;數據并行Distributed Data Parallelism&#xff08;DDP&#xff09;分布式數據并行Zero Redundancy Optimizer&#xff08;ZeRO&#xff09;零冗余優化器 …

陸游的《詩人苦學說》:從藻繪到“功夫在詩外”(中英雙語)mastery lies beyond poetry

陸游的《詩人苦學說》&#xff1a;從藻繪到“功夫在詩外” 今天看萬維鋼的《萬萬沒想到》一書&#xff0c;看到陸游的功夫在詩外的句子&#xff0c;特意去查找這首詩的原文。故而有此文。 我國學人還往往過分強調“功夫在詩外”這句陸游的名言&#xff0c;認為提升綜合素質是一…

DeepSeek-R1 低成本訓練的根本原因是?

在人工智能領域&#xff0c;大語言模型&#xff08;LLM&#xff09;正以前所未有的速度發展&#xff0c;驅動著自然語言處理、內容生成、智能客服等眾多應用的革新。然而&#xff0c;高性能的背后往往是高昂的訓練成本&#xff0c;動輒數百萬美元的投入讓許多企業和研究機構望而…

JavaScript面向對象編程:Prototype與Class的對比詳解

JavaScript面向對象編程&#xff1a;Prototype與Class的對比詳解 JavaScript面向對象編程&#xff1a;Prototype與Class的對比詳解引言什么是JavaScript的面向對象編程&#xff1f;什么是Prototype&#xff1f;Prototype的定義Prototype的工作原理示例代碼優點缺點 什么是JavaS…