【问题标题】:C++ unary right fold vs unary left fold with comma operatorC ++一元右折叠与逗号运算符的一元左折叠
【发布时间】:2018-04-16 14:16:26
【问题描述】:

为什么逗号分隔的一元左折叠会产生与右折叠相同的结果?

Live code

template<class ...Args>
void right_fold(Args... args){
    ((std::cout << args),...);
}

template<class ...Args>
void left_fold(Args... args){
    (...,(std::cout << args));
}

int main()
{
    right_fold(1,2,3,4);
    std::cout << std::endl;
    left_fold(1,2,3,4);
}

输出:

1234
1234

不应该是:

4321
1234

?

【问题讨论】:

标签: c++ c++17 fold-expression


【解决方案1】:

左右折叠是((a,b),c)(a,(b,c))之间的区别,但是当使用内置,运算符时它们具有完全相同的效果:它们首先计算a,然后计算b和最后c。要查看差异,您需要使用带有自定义重载 , 运算符的类型。

语法看起来好像会反转参数,但不,这不会发生。

【讨论】:

  • 为什么((a,b),c)(a,(b,c))的执行顺序一样?
  • @tower120 第一个表示“首先,评估 a 然后 b,然后评估 c”。第二个意思是“首先,评估a,然后评估b,然后评估c”。最终效果是一样的。
  • @tower120 括号确实有效,但它们几乎从未指定评估顺序。这与其他运营商没有什么不同。给定的f() * (g() + h())fgh 可以按任何顺序调用。无需先致电gh
  • @tower120 没错。有一些运算符会强制从左到右进行评估,这些运算符在标准中被特别指出。从 C++17 开始,有一些运算符强制从右到左求值,标准中也提到了这些运算符。对于其他运算符,顺序完全取决于实现。
【解决方案2】:

这些折叠分别展开为:

((std::cout << 1), ((std::cout << 2), ((std::cout << 3), (std::cout << 4))))

...和:

((((std::cout << 1), (std::cout << 2)), (std::cout << 3)), (std::cout << 4))

尽管有很多括号,但它们在执行顺序上是等价的:从左到右。

【讨论】:

    【解决方案3】:

    因为它们确实是同一回事:

    ((std::cout << 1, std::cout << 2), std::cout << 3), std::cout << 4;
    std::cout << 1, (std::cout << 2, (std::cout << 3, std::cout << 4));
    

    两者都有输出1234

    【讨论】:

      猜你喜欢
      • 2014-09-03
      • 2017-04-11
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 2013-04-13
      • 2015-04-12
      • 1970-01-01
      • 2015-10-13
      相关资源
      最近更新 更多