【问题标题】:Why doesn't a left fold expression invert the output of a right fold expression?为什么左折叠表达式不反转右折叠表达式的输出?
【发布时间】:2015-06-13 14:07:49
【问题描述】:

我正在看 C++17 fold expressions,我想知道为什么下面的程序输出

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

Live Example

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

6 5 4

为什么结果是一样的?

【问题讨论】:

    标签: c++ templates c++14 fold-expression


    【解决方案1】:

    根据 § 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))); 
    }
    

    所以表达式具有与comma operator 定义的相同的求值顺序,因此输出是相同的。

    致谢:感谢我的朋友 Marco 首先提出最初的问题,并让我有机会解决这个可能误导的问题。 p>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-20
      相关资源
      最近更新 更多