【问题标题】:Associativity of fold-expressions折叠表达式的关联性
【发布时间】:2016-02-02 20:28:53
【问题描述】:

N4191 向 C++ 提出了折叠表达式。那里的定义是这样的

(args + ...)

是一个左折叠(即(((a0 + a1) + a2) + ...),而那个

(... + args) 

是一个右折叠(即(... + (a8 + (a9 + a10)))。但是,修改后的论文N4295颠倒了左右一元折叠的定义。

问题:原因是什么?从左到右评估(args + ...) 似乎更直观(至少当您习惯于从左到右的字母表时)。

【问题讨论】:

  • 我只想问 Richard 或 Andrew :)
  • 我不知道他们的基本原理,但对我来说(... + args) 看起来像是左折叠(((... + a8) + a9) + a10) 的子表达式。同样(args + ...) 看起来像右折叠(a0 + (a1 + (a2 ...))) 的子表达式。
  • @user2079303 a + b + c 的左关联通常定义为 (a + b) + c,你使用的是相反的
  • 另外,考虑一下二进制折叠的一致性。你真的希望(std::cout << ... << args) 工作......

标签: c++ language-lawyer c++17 associativity fold-expression


【解决方案1】:

来自@cpplearner 的评论,这是来自标准讨论的一些考古学

2015 年 2 月 4 日星期三凌晨 1:30,@T.C. wrote

在 N4295 中,实际上被投票纳入标准,

(... op e) 是一元左折叠;

(e op ...) 是一元右折叠;

然而,在 N4191 中,

(e op ...) 称为左折叠。

(... op e) 称为右折叠。

为什么要转 180 度?

@RichardSmith 的答案

原始论文中的表格只是一个错字。这里有一些 投票纳入标准的定义的原因是 正确一个:

  1. 在标准的表述中,(e op ...) 具有(e_i op <stuff>) 形式的子表达式。它没有 形成(<stuff> op e_i)。这与所有其他包一致 扩展,其中扩展包括重复的实例 模式。

  2. (e op ... op eN),其中eN 是非包,必须将eN 作为最里面的操作数才能有用——也就是说,它必须是 (e1 op (e2 op (e3 op (... op eN)...))),而不是 (...(((e1 op e2) op e3) op ...) op eN)——(e0 op ... op e) 反之亦然。这允许, 例如,(string() + ... + things)(std::cout << ... << things) 工作。为保持一致,(e op ...) 也必须是 (e1 op (e2 op (...)))

【讨论】:

    【解决方案2】:

    我不能代表提案,但新的、交换的定义对我来说似乎很自然。我的理由是(... + args) 是左折叠的子表达式,(args + ...) 是右折叠的子表达式。事实上,前者是最后一段,后者是表达式的初始段(我可能没有使用正确的术语)。

    以下是我将如何从语法中说明折叠的扩展:

    向左折叠

                         (... + args)
                 (... + args) + a999)
         (... + args) + a998) + a999)
    
    ((...((a0 + a1) + a2)...) + a999)
    

    右折叠

    (args + ...)
    (a0 + (args + ...)
    (a0 + (a1 + (args + ...)
    
    (a0 + (...(a997 + (a998 + a999))...))
    

    【讨论】:

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