<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
前文我們實現了一個my_move函數,用來模擬stl的move操作,實現去參照的功能。其內部的原理就是通過remove_reference實現去參照操作。
有時我們也需要保留原型別的左值或者右值屬性,進行原樣轉發,此時就要用forward實現轉發功能。
我們先定義一個模板函數
template <typename F, typename T1, typename T2> void flip1(F f, T1 t1, T2 t2) { f(t2, t1); }
flip1內部呼叫了函數f
我們寫一個函數測試
void ftemp(int v1, int &v2) { cout << v1 << " " << ++v2 << endl; } void use_ftemp(){ int j = 100; int i = 99; flip1(ftemp, j, 42); cout << "i is " << i << " j is " << j << endl; }
通過列印發現i和j的值沒有變化,因為ftemp的v2引數雖然是參照,但是是flip1的形參t1的參照
t1只是形參,修改t1並不能影響外邊的實參j。
想要達到修改實參的目的,需要將flip1的引數修改為參照,我們先實現修改後的版本flip2
template <typename F, typename T1, typename T2> void flip2(F f, T1 &&t1, T2 &&t2) { f(t2, t1); }
我們定義了一個flip2函數,t1和t2分別是右值參照型別。接下來用一個測試函數進行測試
int j = 100; int i = 99; flip2(ftemp, j, 42); cout << "i is " << i << " j is " << j << endl;
這次我們發現j被修改了,因為flip2的t1引數型別為T1的右值參照,當把實參j賦值給flip2時,T1變為int&,
t1的型別就是int& &&,通過摺疊t1變為int&型別。這樣t1就和實參j繫結了,在flip2內部修改t1,就達到了修改j的目的。
但是flip2同樣存在一個問題,如果flip2的第一個引數f,如果f是一個接受右值參照引數的函數,會出現編譯錯誤。
為說明這一點,我們實現一個接納模板引數右值參照型別的函數
void gtemp(int &&i, int &j) { cout << "i is " << i << " j is " << j << endl; }
此時如果我們將gtemp作為引數傳遞給flip2會報錯
int j = 100; int i = 99; // flip2(gtemp, j, 42) 會報錯 // 因為42作為右值純遞給flip2,t2會被摺疊為int&型別 // t2傳遞給gtemp第一個引數時,int&&無法系結int&型別 //flip2(gtemp, i, 42); cout << "i is " << i << " j is " << j << endl;
當我們將42傳遞給flip2第二個引數時,T2被範例化為int型別,t2就變為int && 型別,通過摺疊t2變為int&型別。
t2作為引數傳遞給gtemp的第一個引數時會報錯,
cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
因為t2是一個左值,右值無法系結該左值。
解決的辦法就是實現一個flip函數,內部實現對T2,T1型別的原樣轉發。
template <typename F, typename T1, typename T2> void flip(F f, T1 &&t1, T2 &&t2) { f(std::forward<T2>(t2), std::forward<T1>(t1)); }
通過forward將t2型別轉化為和T2型別一樣的型別,也就是int的右值型別,接下來的呼叫就不會出問題了
void use_ftemp() { int j = 100; int i = 99; flip(gtemp, i, 42); cout << "i is " << i << " j is " << j << endl; }
模板同樣支援可變引數
//可變引數的函數模板 template <typename T> ostream &print(ostream &os, const T &t) { return os << t; //輸出最後一個元素 } template <typename T, typename... Args> ostream &print(ostream &os, const T &t, const Args &...rest) { os << t << ", "; return print(os, rest...); }
Args是可變的模板引數包, 然後再用Args定義rest變數,這是一個可變參數列。
我們的模板函數print內部呼叫stl的print函數,通過對rest…實現展開操作。
呼叫過程可按如下的方式
void use_printtemp() { int i = 100; string s = "hello zack!!!"; print(cout, i, s, 42); }
第一次呼叫print實際是呼叫的可變引數的print,之後才呼叫沒有可變引數的print函數。
本文介紹了模板型別的原樣轉發,以及多模板參數列的使用。
到此這篇關於淺析C++模板型別中的原樣轉發和可變引數有什麼意義的文章就介紹到這了,更多相關C++原樣轉發和可變引數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45