N4191 proposed fold-expressions to C++. The definition there was that
(args + ...)
is a left-fold (i.e. (((a0 + a1) + a2) + ...)
, and that
(... + args)
is a right-fold (i.e. (... + (a8 + (a9 + a10)))
. However, the revised paper N4295 reversed the definitions of left and right unary folds.
Question: what is the rationale? It seems more intuitive (at least when you are used to left-to-right alphabets) to evaluate (args + ...)
from left-to-right.
From the comment by @cpplearner, here's some archeology from std-discussion
On Wed, Feb 4, 2015 at 1:30 AM, @T.C. wrote:
In N4295, which was actually voted into the standard,
(... op e)
is a unary left fold;
(e op ...)
is a unary right fold;In N4191, however,
(e op ...)
is called a left fold.
(... op e)
is called a right fold.Why the 180-degree turn?
And the answer by @RichardSmith
The form in the original paper was simply a typo. Here are some reasons why the definition that was voted into the standard is the correct one:
In the standard's formulation,
(e op ...)
has subexpressions of the form(e_i op <stuff>)
. It does not have subexpressions of the form(<stuff> op e_i)
. This is consistent with all other pack expansions, where the expansion comprises repeated instances of the pattern.
(e op ... op eN)
, whereeN
is a non-pack, must haveeN
as the innermost operand in order to be useful -- that is, it must be(e1 op (e2 op (e3 op (... op eN)...)))
, not(...(((e1 op e2) op e3) op ...) op eN)
-- and vice versa for(e0 op ... op e)
. This allows, for instance,(string() + ... + things)
and(std::cout << ... << things)
to work. For consistency,(e op ...)
must also be(e1 op (e2 op (...)))
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With