網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
淺析C++模板類型中的原樣轉(zhuǎn)發(fā)和可變參數(shù)的實(shí)現(xiàn)_C 語(yǔ)言
作者:戀戀風(fēng)辰 ? 更新時(shí)間: 2022-10-04 編程語(yǔ)言原樣轉(zhuǎn)發(fā)的意義
前文我們實(shí)現(xiàn)了一個(gè)my_move函數(shù),用來(lái)模擬stl的move操作,實(shí)現(xiàn)去引用的功能。其內(nèi)部的原理就是通過(guò)remove_reference實(shí)現(xiàn)去引用操作。
有時(shí)我們也需要保留原類型的左值或者右值屬性,進(jìn)行原樣轉(zhuǎn)發(fā),此時(shí)就要用forward實(shí)現(xiàn)轉(zhuǎn)發(fā)功能。
我們先定義一個(gè)模板函數(shù)
template <typename F, typename T1, typename T2>
void flip1(F f, T1 t1, T2 t2)
{
f(t2, t1);
}
flip1內(nèi)部調(diào)用了函數(shù)f
我們寫(xiě)一個(gè)函數(shù)測(cè)試
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;
}
通過(guò)打印發(fā)現(xiàn)i和j的值沒(méi)有變化,因?yàn)閒temp的v2參數(shù)雖然是引用,但是是flip1的形參t1的引用
t1只是形參,修改t1并不能影響外邊的實(shí)參j。
想要達(dá)到修改實(shí)參的目的,需要將flip1的參數(shù)修改為引用,我們先實(shí)現(xiàn)修改后的版本flip2
template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)
{
f(t2, t1);
}
我們定義了一個(gè)flip2函數(shù),t1和t2分別是右值引用類型。接下來(lái)用一個(gè)測(cè)試函數(shù)進(jìn)行測(cè)試
int j = 100;
int i = 99;
flip2(ftemp, j, 42);
cout << "i is " << i << " j is " << j << endl;
這次我們發(fā)現(xiàn)j被修改了,因?yàn)閒lip2的t1參數(shù)類型為T1的右值引用,當(dāng)把實(shí)參j賦值給flip2時(shí),T1變?yōu)閕nt&,
t1的類型就是int& &&,通過(guò)折疊t1變?yōu)閕nt&類型。這樣t1就和實(shí)參j綁定了,在flip2內(nèi)部修改t1,就達(dá)到了修改j的目的。
但是flip2同樣存在一個(gè)問(wèn)題,如果flip2的第一個(gè)參數(shù)f,如果f是一個(gè)接受右值引用參數(shù)的函數(shù),會(huì)出現(xiàn)編譯錯(cuò)誤。
為說(shuō)明這一點(diǎn),我們實(shí)現(xiàn)一個(gè)接納模板參數(shù)右值引用類型的函數(shù)
void gtemp(int &&i, int &j)
{
cout << "i is " << i << " j is " << j << endl;
}
此時(shí)如果我們將gtemp作為參數(shù)傳遞給flip2會(huì)報(bào)錯(cuò)
int j = 100;
int i = 99;
// flip2(gtemp, j, 42) 會(huì)報(bào)錯(cuò)
// 因?yàn)?2作為右值純遞給flip2,t2會(huì)被折疊為int&類型
// t2傳遞給gtemp第一個(gè)參數(shù)時(shí),int&&無(wú)法綁定int&類型
//flip2(gtemp, i, 42);
cout << "i is " << i << " j is " << j << endl;
當(dāng)我們將42傳遞給flip2第二個(gè)參數(shù)時(shí),T2被實(shí)例化為int類型,t2就變?yōu)閕nt && 類型,通過(guò)折疊t2變?yōu)閕nt&類型。
t2作為參數(shù)傳遞給gtemp的第一個(gè)參數(shù)時(shí)會(huì)報(bào)錯(cuò),
cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
因?yàn)閠2是一個(gè)左值,右值無(wú)法綁定該左值。
解決的辦法就是實(shí)現(xiàn)一個(gè)flip函數(shù),內(nèi)部實(shí)現(xiàn)對(duì)T2,T1類型的原樣轉(zhuǎn)發(fā)。
template <typename F, typename T1, typename T2>
void flip(F f, T1 &&t1, T2 &&t2)
{
f(std::forward<T2>(t2), std::forward<T1>(t1));
}
通過(guò)forward將t2類型轉(zhuǎn)化為和T2類型一樣的類型,也就是int的右值類型,接下來(lái)的調(diào)用就不會(huì)出問(wèn)題了
void use_ftemp()
{
int j = 100;
int i = 99;
flip(gtemp, i, 42);
cout << "i is " << i << " j is " << j << endl;
}
模板的可變參數(shù)
模板同樣支持可變參數(shù)
//可變參數(shù)的函數(shù)模板
template <typename T>
ostream &print(ostream &os, const T &t)
{
return os << t; //輸出最后一個(gè)元素
}
template <typename T, typename... Args>
ostream &print(ostream &os, const T &t, const Args &...rest)
{
os << t << ", ";
return print(os, rest...);
}
Args是可變的模板參數(shù)包, 然后再用Args定義rest變量,這是一個(gè)可變參數(shù)列表。
我們的模板函數(shù)print內(nèi)部調(diào)用stl的print函數(shù),通過(guò)對(duì)rest…實(shí)現(xiàn)展開(kāi)操作。
調(diào)用過(guò)程可按如下的方式
void use_printtemp()
{
int i = 100;
string s = "hello zack!!!";
print(cout, i, s, 42);
}
第一次調(diào)用print實(shí)際是調(diào)用的可變參數(shù)的print,之后才調(diào)用沒(méi)有可變參數(shù)的print函數(shù)。
總結(jié)
本文介紹了模板類型的原樣轉(zhuǎn)發(fā),以及多模板參數(shù)列表的使用。
視頻鏈接
源碼鏈接
原文鏈接:https://blog.csdn.net/secondtonone1/article/details/125399321
相關(guān)推薦
- 2022-06-16 golang?gorm開(kāi)發(fā)架構(gòu)及寫(xiě)插件示例_Golang
- 2022-09-14 python重寫(xiě)方法和重寫(xiě)特殊構(gòu)造方法_python
- 2024-04-08 Spring在多線程環(huán)境下如何確保事務(wù)一致性
- 2022-07-30 Linux常見(jiàn)命令-搜索查詢類,find 查找文件或者目錄,locate 快速定位文件路徑,grep
- 2022-04-15 使用PyInstaller?打包配置文件_python
- 2022-05-10 thymeleaf跳轉(zhuǎn)到響應(yīng)頁(yè)面(modelandview 中的view)
- 2022-04-16 統(tǒng)計(jì)C語(yǔ)言二叉樹(shù)中葉子結(jié)點(diǎn)個(gè)數(shù)_C 語(yǔ)言
- 2022-10-09 ASP.NET?Core?5.0中的Host.CreateDefaultBuilder執(zhí)行過(guò)程解析_
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支