I'm taking a look at C++17 fold expressions and I'm wondering why does the following program outputs
4 5 6
4 5 6
for both of the for_each
calls
template<typename F, typename... T>
void for_each1(F fun, T&&... args)
{
(fun (std::forward<T>(args)), ...);
}
template<typename F, typename... T>
void for_each2(F fun, T&&... args)
{
(..., fun (std::forward<T>(args)));
}
int main()
{
for_each1([](auto i) { std::cout << i << std::endl; }, 4, 5, 6);
std::cout << "-" << std::endl;
for_each2([](auto i) { std::cout << i << std::endl; }, 4, 5, 6);
}
Live Example
I thought that the second fold expression was meant to output the numbers in reverse order
6 5 4
How come the results are the same?
According to § 14.5.3/9
The instantiation of a fold-expression produces:
(9.1) — ((E1 op E2) op · · · ) op EN for a unary left fold,
(9.2) — E1 op (· · · op (EN-1 op EN )) for a unary right fold,
(9.3) — (((E op E1) op E2) op · · · ) op EN for a binary left fold, and
(9.4) — E1 op (· · · op (EN-1 op (EN op E))) for a binary right fold
In each case, op is the fold-operator, N is the number of elements in the pack expansion parameters, and each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith element.
in the code above they're both unary fold expressions and their expansion is
template<typename F, typename... T>
void for_each1(F fun, T&&... args) {
// Unary right fold (fun(args_0) , (fun(args_1) , (fun(args_2) , ...)))
(fun (std::forward<T>(args)), ...);
}
template<typename F, typename... T>
void for_each2(F fun, T&&... args) {
// Unary left fold ((fun(args_0) , fun(args_1)) , fun(args_2)) , ...
(..., fun (std::forward<T>(args)));
}
so the expressions have the same evaluation order as defined by the comma operator and thus the output is the same.
Credits: thanks to my friend Marco who raised the original question in the first place and gave me the chance to solve this potentially-misleading issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With