C++17 Fold Expressions
阿新 • • 發佈:2020-09-03
C++17 Fold Expressions
本文介紹C++17新特性摺疊表示式。文章示例程式碼通過MinGW編譯,巨集__cplusplus=201703
下面我們從一個模板函式sum開始,介紹摺疊表示式。
用摺疊表示式簡化以前的程式碼
C++11引入了變長引數模板,我們想求變長引數的和,可以這樣寫模板函式
template <typename T> auto sum(T arg){ return arg; } template <typename T1, typename... T> auto sum(T1 arg, T... args){ return arg + sum(args...); } int main() { std::cout<<sum(1,2,3)<<std::endl; return 0; }
注:這裡用到了auto推導,C++14編譯沒問題。用C++11編譯的讀者記得在函式簽名後面加"-> T"
為了完成sum這個函式,我們需要寫2個函式。一個進行遞迴,一個作為遞迴返回條件。這種模板的遞迴是在編譯時發生的,遇到複雜的遞迴會大大加大編譯時間。有沒有辦法寫一個模板函式,同時又能實現sum功能呢?
有,就是摺疊表示式
我們看下摺疊表示式的寫法
template <typename... T> auto sum_folder(T... args) { return (... + args); } int main() { std::cout<<sum_folder(1,2,3)<<std::endl; return 0; }
這裡摺疊表示式會將sum_folder(1,2,3)擴充套件成(1+(2+3))
如何使用摺疊表示式
看了上面的例子,相信讀者對摺疊表示式已經有了直觀的認識。下面我們詳細介紹下摺疊表示式的使用。
一元摺疊
假設引數是args,操作符是op。一元摺疊有兩種情況:左摺疊和右摺疊
- unary left fold: (... op args) expends to ((arg1 op arg2) op arg3) + ...
- unary right fold: (args op ...) expends to arg1 op (arg2 op ... (argN-1 op argN))
舉2個例子方便理解
左摺疊
template<typename... T>
string combine_str_left(T... args) {
return (... + args);
}
string s("head");
// expand to (s+" ") + "tail"
std::cout<<combine_str_left(s," ","tail")<<std::endl;
右摺疊
template<typename... T>
string combine_str_right(T... args) {
return (args + ...);
}
右摺疊就不能combine_str_right(s," ", "tail")這麼寫,因為擴充套件開來是s + (" " + "tail")顯然兩個字面值是不能直接相加的。所以比起右摺疊,左摺疊用的比較多。
二元摺疊
- binary left fold: (value op ... op args) expand to ((value op arg1) op arg2) op ...
- binary right fold: (args op ... op value) expand to args1 op (arg2 op ... ( argN op value))