高端知識(shí)點(diǎn):折疊表達(dá)式(我也是第一次知道)

The sports meet
跑得慢,會(huì)遭遇殘酷,跑得快,才能遇到激蕩
不知道大家以前了解折疊表達(dá)式不,這里介紹一下!
我也是最近才知道這個(gè)知識(shí)點(diǎn),在C++中通過折疊表達(dá)式可以更容易的在可變參數(shù)模板中處理可變參數(shù)。
先看一下傳統(tǒng)的使用遞歸方式來(lái)處理可變參數(shù)的代碼:
void print(int i) {std::cout << i << " ";}void func() {}template<typename T1, typename... Tn>void func(T1 arg1, Tn... args) {print(arg1);func(args...);}int main() {func(2, 3, 4);std::cout << "Hello World \n";}
注意看代碼里還需要有個(gè)不帶參數(shù)的func()來(lái)停止遞歸。很麻煩!
而使用折疊表達(dá)式,通過單個(gè)函數(shù)模板就可以實(shí)現(xiàn)上述功能,不需要多余的函數(shù),看代碼:
void print(int i) {std::cout << i << " ";}template<typename... T>void func(const T&... args) {(print(args), ...);std::cout << "\n";}int main() {func(1, 2, 3);std::cout << "Hello World \n";}
函數(shù)體中的三個(gè)點(diǎn)觸發(fā)折疊。它會(huì)針對(duì)可變參數(shù)中的每個(gè)參數(shù)調(diào)用print(),對(duì)print()的每個(gè)調(diào)用用逗號(hào)分隔。
例如對(duì)于func(1, 2, 3),函數(shù)內(nèi)的折疊表達(dá)式會(huì)展開成這樣:
(print(1), (print(2), print(3)));再用一個(gè)例子鞏固下:
template<typename... T>void func(const T&... args) {((std::cout << args << " "), ...);std::cout << "\n";}int main() {func(1, 2, 3);std::cout << "Hello World \n";}
下面是折疊表達(dá)式展開后的形式:
((std::cout << 1<< " "), ((std::cout << 2 << " "), (std::cout << 3 << " ")));上面的示例中都是與逗號(hào)運(yùn)算符結(jié)合使用,但實(shí)際上折疊可以和任何類型的運(yùn)算符結(jié)合使用。例如與加號(hào)結(jié)合使用來(lái)計(jì)算所有值的和:
template<typename T, typename... Tn>int sum(const T& v, const Tn&... values) {return (v + ... + values);}template<typename... Tn>int sum2(const Tn&... values) {return (... + values);}int main() {std::cout << sum(1, 2, 3, 4) << "\n";std::cout << sum2(1, 2, 3, 4) << "\n";std::cout << "Hello World \n";}
對(duì)于sum(1, 2, 3, 4),展開的形式如下:
return (((1 + 2) + 3) + 4);但這里有個(gè)問題,該函數(shù)的使用一定需要至少一個(gè)參數(shù),否則將無(wú)法通過編譯:
template<typename T, typename... Tn>int sum(const T& v, const Tn&... values) {return (v + ... + values);}int main() {sum();std::cout << "Hello World \n";}
報(bào)錯(cuò)如圖:

長(zhǎng)度為0其實(shí)也可以使用折疊表達(dá)式,但不能和加減這種運(yùn)算符結(jié)合使用,只能和邏輯與、邏輯或和逗號(hào)結(jié)合使用。例如:
template <typename... Values>double allTrue(const Values&... values) {return (... && values);}template <typename... Values>double anyTrue(const Values&... values) {return (... || values);}int main() {std::cout << allTrue(1, 1, 0) << allTrue(1, 1) << allTrue() << "\n"; // 011std::cout << anyTrue(1, 1, 0) << anyTrue(0, 0) << anyTrue() << "\n"; // 100}
關(guān)于折疊表達(dá)式的介紹就到這里,打完收工!希望對(duì)大家有所幫助!
參考資料:
《Professional C++》
