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)
, where eN
is a non-pack, must have eN
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 (...)))
.
(... + args)
looks like a sub-expression of the left fold(((... + a8) + a9) + a10)
. And similarly(args + ...)
looks like a sub expression of right fold(a0 + (a1 + (a2 ...)))
. – Vespuccia + b + c
is commonly defined as (a + b) + c, you are using the opposite – Million(std::cout << ... << args)
to work... – Crosspatch