網站首頁 編程語言 正文
原樣轉發的意義
前文我們實現了一個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函數。
總結
本文介紹了模板類型的原樣轉發,以及多模板參數列表的使用。
視頻鏈接
源碼鏈接
原文鏈接:https://blog.csdn.net/secondtonone1/article/details/125399321
相關推薦
- 2022-10-01 windows?server?2016?搭建FTP服務器詳細教程_FTP服務器
- 2023-05-07 Go項目配置管理神器之viper的介紹與使用詳解_Golang
- 2023-07-27 原型和原型鏈條、ES6、前后端交互Ajax
- 2022-03-27 C++編輯距離(動態規劃)_C 語言
- 2023-04-07 C語言中循環嵌套的應用方式_C 語言
- 2022-08-07 API處理Android安全距離詳情_Android
- 2022-08-16 C#?IEnumerator枚舉器的具體使用_C#教程
- 2022-05-28 python中flatten()參數示例詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支