12

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

(args + ...)

是一个左折叠(即(((a0 + a1) + a2) + ...),并且

(... + args) 

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

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

4

2 回答 2

10

从@cpplearner 的评论中,这是来自 std-discussion 的一些考古学

2015 年 2 月 4 日星期三凌晨 1:30,@TC 写道

在实际上被投票纳入标准的 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 (...))).

于 2016-02-03T15:31:58.660 回答
6

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

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

左折叠

                     (... + args)
             (... + args) + a999)
     (... + args) + a998) + a999)

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

右折叠

(args + ...)
(a0 + (args + ...)
(a0 + (a1 + (args + ...)

(a0 + (...(a997 + (a998 + a999))...))
于 2016-02-02T21:54:21.307 回答