为什么左折表达式不反转右折表达式的输出?

Why doesn't a left fold expression invert the output of a right fold expression?

本文关键字:表达式 输出 为什么      更新时间:2023-10-16

我正在查看C++17折表达式,我想知道为什么以下程序输出

4 5 6 
4 5 6 

对于两个for_each呼叫

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);
}

现场示例

我认为第二个折叠表达式旨在以相反的顺序输出数字

6 5 4

为什么结果是一样的?

根据 § 14.5.3/9

折叠表达式的实例化产生:

(9.1) — ((E1 op E2) op · · · ) op EN 表示一元左折,

(9.2) — E1 op (· · op (EN-1 op EN )) 表示一元右折,

(9.3) — (((E op E1) op E2) op · · · ) op EN 表示二进制左折,以及

(9.4) — E1 op (· · op (EN-1 op (EN op E))) 用于二进制右折

在每种情况下,op 是折叠运算符,N 是包扩展参数中的元素数,每个 Ei 都是通过实例化模式并用其第 i 个元素替换每个包扩展参数来生成的。

在上面的代码中,它们都是一元折叠表达式,它们的扩展是

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))); 
}
因此,

表达式具有与逗号运算符定义的相同计算顺序,因此输出是相同的。

学分:感谢我的朋友Marco,他首先提出了最初的问题,并给了我解决这个可能具有误导性的问题的机会。