![C++98元編程技術解析_第1頁](http://file4.renrendoc.com/view/5ee310de38360a61c35e65831ead6f0f/5ee310de38360a61c35e65831ead6f0f1.gif)
![C++98元編程技術解析_第2頁](http://file4.renrendoc.com/view/5ee310de38360a61c35e65831ead6f0f/5ee310de38360a61c35e65831ead6f0f2.gif)
![C++98元編程技術解析_第3頁](http://file4.renrendoc.com/view/5ee310de38360a61c35e65831ead6f0f/5ee310de38360a61c35e65831ead6f0f3.gif)
![C++98元編程技術解析_第4頁](http://file4.renrendoc.com/view/5ee310de38360a61c35e65831ead6f0f/5ee310de38360a61c35e65831ead6f0f4.gif)
![C++98元編程技術解析_第5頁](http://file4.renrendoc.com/view/5ee310de38360a61c35e65831ead6f0f/5ee310de38360a61c35e65831ead6f0f5.gif)
版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第第頁C++98元編程技術解析人們往往會將一個大問題(拆解)成許多小問題,通過解決一個個小問題,最終就能解決整個大問題。
若是拆解過后,這些小問題的處理邏輯不變,變化的只是輸入狀態(tài),那么此時就是一種代碼復用。對應編程世界,一種是自上而下的拆解組合方式,稱為遞歸;一種是自下而上的拆解組合方式,稱為迭代。
拆解后還能組合,拆解才有意義,遞歸和迭代本身就帶有一種約束,必須具備起始狀態(tài)和終止狀態(tài)。若是沒有起始狀態(tài),遞歸就沒有起點,循環(huán)就沒有開始;若是沒有終止狀態(tài),遞歸就沒有終點,循環(huán)就沒有結束,
本文所說的元(編程)拆解技術,就是編譯期的問題拆解與組合技術,編譯期不像運行期那樣能夠動態(tài)地改變輸入與輸出狀態(tài),(C++)誕生了許多技術來解決這個問題,這便是后文要介紹的。
本文以一個需求為例,來講解這些技術:
要求編寫一個unroll(callb(ac)k)函數(shù),該函數(shù)將調用N次傳入的callback函數(shù)。
起始狀態(tài)就是N,終止狀態(tài)就是N為零,拆解后處理邏輯不變的小問題就是callback。
先不看文,你首先想到的是什么解法?文讀畢,對比一下文中的各種拆解技術思路,獲益更多。
原始遞歸法
模板元編程最開始就只支持遞歸這一種拆解方式,每次輸入一個狀態(tài),依次產(chǎn)生下一個狀態(tài),若狀態(tài)與遞歸終止狀態(tài)相同,則結束。
采用這種方式,實現(xiàn)需求如下:
1namespace
cpp98
{23
//
declara(ti)on4
(te)mplate
void
unroll(F);56
template
7
struct
unroll_helper
{8
void
operator()(F
f)
{9
f();10
unroll(f);11
}12
};1314
//
terminated
state15
template
16
struct
unroll_helper
{17
void
operator()(F)
{}18
};1920
//
definition21
template
22
void
unroll(F
f)
{23
unroll_helper()(f);24
}2526
void
print_cpp98()
{27
std::puts("hello
cpp98");28
}29}3031int
main()
{32
cpp98::unroll(cpp98::print_cpp98);33
//
output:34
//
hello
cpp9835
//
hello
cpp9836}
由于函數(shù)模板不支持偏特化,于是需要借助一個unroll_helper類模板,來實現(xiàn)遞歸終止條件,再在unroll函數(shù)中調用該幫助類,不斷拆解問題。
遞歸輸入條件N為起始狀態(tài),每次拆解執(zhí)行完成之后,通過N-1得到下一個狀態(tài),從而不斷解決問題。
這個時期,C++的元編程拆解技術還很弱,一個簡單的需求,實現(xiàn)起來也頗為繁瑣。
可變參數(shù)模板
時間來到C++11,模板元編程迎來強大擴展,非常有用的一個新特性就是可變參數(shù)模板,它能夠讓我們擺脫遞歸這種原始拆解方式。
但是C++11還只是開始,基礎組件不完善,所以并不能非常有效地實現(xiàn)目標。
什么意思呢?看如下這個不太完善的實現(xiàn):
1namespace
cpp11
{23
template
4
class
index_sequence
{};56
template
7
void
unroll(F
f,
index_sequence)
{8
using
expand
=
std::size_t[];9
expand{
(f(),
Is)...
};10
}1112}131415int
main()
{16
cpp11::unroll([]
{
std::puts("hello
cpp11");
},17
cpp11::index_sequence());18}
原始遞歸法是采用不斷遞歸來動態(tài)地產(chǎn)生狀態(tài),而有了可變參數(shù)模板,狀態(tài)可以直接在編譯期初期產(chǎn)生,從而直接拿來用就可以。
這里定義了一個index_sequence用來接收所有狀態(tài),然后借助一些逗號表達式技巧展開參數(shù)包,在參數(shù)包展開的過程當中,執(zhí)行處理邏輯。
C++11起也支持Lambda,因此也不用再提供一個額外的調用函數(shù)。
這個實現(xiàn)的唯一缺點就是由于缺乏相應的組件,需要手動產(chǎn)生狀態(tài),導致使用起來較為麻煩。
完善版可變參數(shù)模板
C++14增加了std::index_sequence和std::make_index_sequence,于是就能將手動產(chǎn)生狀態(tài)變成動態(tài)產(chǎn)生,完善實現(xiàn)。
代碼如下:
1namespace
cpp14
{23
template
4
void
helper(F
f,
std::index_sequence)
{5
using
expand
=
std::size_t[];6
expand{
(f(),
Is)...
};7
}89
//
variable
template10
template
11
auto
unroll
=
[](auto
f)
{
//
generic
lambda12
helper(f,
std::make_index_sequence{});13
};14}1516int
main()
{17
cpp14::unroll([]
{
std::puts("hello
cpp14");
});18}
同時,C++14還支持variabletemplate和genericlambda,這進一步簡化了實現(xiàn)。
FoldExpression
前面的方式是采用逗號表達式技巧來展開參數(shù)包,C++17支持Foldexpression,可以直接展開,因此代碼得到進一步簡化。
變成:
1namespace
cpp17
{23
template
4
void
helper(F
f,
std::index_sequence)
{5
((f(),
Is),
...);
//
fold
expression6
}78
template
9
auto
unroll
=
[](auto
f)
{
//
generic
lambda10
helper(f,
std::make_index_sequence{});11
};12}
constexprif
C++17的另一種拆解技術是借助constexprif,它的好處在于能夠直接在本函數(shù)內(nèi)判斷終止狀態(tài),這樣就不再需要去定義一個遞歸終止函數(shù)。
1namespace
cpp17
{2
//
variable
template
+
constexpr
if3
template
4
auto
unroll
=
[](auto
expr)
{5
if
constexpr
(N)
{6
expr();7
unroll(expr);8
}9
};10}1112int
main()
{13
cpp17::unroll([]
{
std::puts("hello
cpp17");
});14}
與原始遞歸法相比,這種方式除了消除遞歸終止函數(shù),還免于編寫一個額外的helper類,genericlambda更是減少了模板參數(shù)。
這是目前為止,最簡潔的實現(xiàn)。
C++20雙層Lambda法
有沒有非遞歸的簡潔拆解方式呢?當然也有。
看如下實現(xiàn):
1namespace
cpp20
{23
template
constexpr
auto
unroll
=
[](auto
f)
{4
[f](std::index_sequence)
{5
((f(),
void(Is)),
...);6
}(std::make_index_sequence());7
};8}910int
main()
{11
cpp20::unroll([]
{
std::puts("hello
cpp20");
});12}
這里的關鍵是C++20的templatelambda,它支持為lambda編寫模板參數(shù),基于此才能夠編寫索引的模板參數(shù)。
Lambda函數(shù)里面再套一個Lambda函數(shù),外層用于提供調用(接口),內(nèi)層用于管理狀態(tài)和處理調用。如果沒有templatelambda,內(nèi)層Lambda的std::index_sequence參數(shù)就無法寫,也就接收不了狀態(tài)。、
StructuredBindingPacks
原本有些新特性是應該在C++23就進入標準的,但由于種種原因,我們只有期望C++26能用上了。Structuredbindingpacks就是這么一個特性。
前面除了遞歸以外的所有拆解方法,都得借助std::index_sequence,這就是代碼依舊復雜的原因所在。
有沒有一種方式可以直接讓我們訪問參數(shù)包,而不必再定義一個參數(shù)為std::index_sequence的函數(shù)才能拿到那些參數(shù)包?Structuredbindingpacks就提供了這一能力。
這是P1061所提出的一種方式,讓我們能夠通過Structuredbindings直接得到參數(shù)包。
于是實現(xiàn)變?yōu)椋?/p>
1namespace
p1061
{23
template
constexpr
auto
unroll
=
[](auto
f)
{4
auto
[...
Is]
=
std::make_index_sequence();5
((f(),
void(Is)),
...);6
};78}910int
main()
{11
p1061::unroll([]
{
std::puts("hello
p1061");
});12}
這種拆解技術才是最直觀的方式,兩行代碼解決一切。
ExpansionStatements
另外一種方式就是我們在反射中經(jīng)常使用到的一個特性:templatef(or)。
這種方式比StructuredBindingPacks更強大,是靜態(tài)反射里面的一個擴展特性,能夠支持編譯期迭代。
對于本次需求的實現(xiàn)為:
1namespace
p1306
{2
template
constexpr
auto
unroll
=
[](auto
f)
{3
constexpr
std::array
dummy{};4
template
for
(auto6
};7}89int
m
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年江西師范高等??茖W校高職單招語文2018-2024歷年參考題庫頻考點含答案解析
- 2025年武漢電力職業(yè)技術學院高職單招語文2018-2024歷年參考題庫頻考點含答案解析
- 航空運輸合同集錦
- 人工智能算法開發(fā)與應用合同
- 幼兒園植樹節(jié)策劃方案2021【五篇】
- 桉樹造林工程承包合同書
- 新企業(yè)之間借款合同范本
- 采購法務與合同管理1
- 咨詢培訓服務合同模板
- 校車租賃合同書
- 2025-2030年中國清真食品行業(yè)運行狀況及投資發(fā)展前景預測報告
- 廣東省茂名市電白區(qū)2024-2025學年七年級上學期期末質量監(jiān)測生物學試卷(含答案)
- 《教育強國建設規(guī)劃綱要(2024-2035年)》全文
- 中國服裝零售行業(yè)發(fā)展環(huán)境、市場運行格局及前景研究報告-智研咨詢(2025版)
- 臨床提高膿毒性休克患者1h集束化措施落實率PDCA品管圈
- 汽車車身密封條設計指南
- 2024建安杯信息通信建設行業(yè)安全競賽題庫(試題含答案)
- JBT 14727-2023 滾動軸承 零件黑色氧化處理 技術規(guī)范 (正式版)
- 術后譫妄及護理
- 醫(yī)藥行業(yè)的市場營銷與渠道拓展
- 壓力管道安全技術監(jiān)察規(guī)程-工業(yè)管道
評論
0/150
提交評論