C++17使用std::apply和fold expression對tuple進行遍歷
C++17使用std::apply和fold expression對std::tuple進行遍歷
std::apply函式
先來看這個std::apply
函式,這個函式定義在tuple
標頭檔案中,函式簽名如下:
template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t);
該函式接受兩個引數,第一個是一個函式物件,第二個是一個Tuple物件
來看一個最簡單的示例:
#include <tuple>
#include <iostream>
int main() {
// 兩個元素相加
std::cout << std::apply([](auto x, auto y) { return x + y; },
std::make_tuple(1, 2.0)) << '\n';
}
輸出結果是3
這個例子中第一個引數使用Lambda匿名函式將tuple
中的兩個元素相加,第二個使用std::make_tuple
函式構造一個只含有兩個元素的tuple
fold expression
這個特性是C++ 17中我覺得很有用的一個新特性,使用規則有下面四條:
-
Unary right fold ( …) becomes ( (… ( )))
-
Unary left fold (… ) becomes ((( ) …) )
-
Binary right fold ( … ) becomes ( (… ( ( ))))
-
Binary left fold ( … ) becomes (((( ) ) …) )
這裡的指的是Expression(符合C++語法的表示式),指的是operator(操作符),是parameter pack(可變引數)的個數,是一個常數。
可能看這個規則有些抽象,我們來看一些具體的例子:
#include <tuple>
#include <iostream>
int main() {
// 多個元素相加,使用parameter pack
std::cout << std::apply([](auto&& ... args) { return (args + ...); },
std::make_tuple(1, 2.f, 3.0)) << '\n';
// 遍歷tuple並輸出,注意逗號操作符的使用
std::apply([](auto&&... args) { ((std::cout << args << '\n'), ...); },
std::make_tuple(1, 2.f, 3.0));
}
輸出如下:
6
1
2
3
第6行中,std::apply
函式的第一個引數是一個Lambda匿名函式,函式的引數是一個可變引數args
,函式體中只有一條語句args + ...
,這個情況就是上面的第一種情況:這裡的就是args
,就是+
,所以展開來就是(因為引數的個數是3)。
第9行中,Lambda匿名函式的函式體是((std::cout << args << '\n'), ...)
這是一個逗號操作符,也屬於上面四種情況中的第一種:這裡的就是std::cout << args << '\n')
,就是,
,所以這一行就列印輸出了tuple
的每一個元素。如果在C++17之前想要遍歷tuple
就比較麻煩,需要很多額外的操作。