- A+

`#include<iostream> using namespace std; template<typename ...Args> void output_argus(Args&&... args) { ((cout << args << '/n'), ...); // #1 (... , (cout << args << '/n')); // #2 } int main() { output_argus(1, "test", 5.6f); } `

Based on c++ operator doc, `','`

is a **left to right operator**. It is meaning `a, b, c, d`

meaning `(((a, b), c),d)`

not `(a, (b, (c, d)))`

. This is important if a, b, c, d are statements.

However, based on fold expression doc, for `','`

which should use **unary left fold**.

My question why both statements in my code are working? Shouldn't only #2 work? And also how to understand `...`

and `args`

. and nested fold expression?

Let's say we're folding 3 expressions over a binary operator, with a unary fold. We have two options here: `(xs @ ...)`

(a unary right fold) and `(... @ xs)`

(a unary left fold).

`(xs @ ...)`

expands out to `(a @ (b @ c))`

`(... @ xs)`

expands out to `((a @ b) @ c)`

What can we say about the difference between the expressions `a @ (b @ c)`

and `(a @ b) @ c`

? If `@`

is **associative** over these types, then those two expressions are identical. That's what associative means. If you had a parameter pack of integers, then a unary left fold over `+`

and a unary right fold over `+`

will have the same value (modulo overflow), because addition is associative. Subtraction, on the other hand, is not associative. `(xs - ...)`

and `(... - xs)`

mean very different things.

Likewise, the `,`

operator in C++ is associative. It doesn't matter which way you parenthesize the expressions. `((a, b), c)`

and `(a, (b, c))`

both evaluate and discard `a`

, then evaluate and discard `b`

, then evaluate `c`

and that's the result. It's easier to see if you reduce the expressions to just letters why this is the case.

As a result, both `((cout << args << '/n'), ...)`

and `(... , (cout << args << '/n'))`

do the same thing, and they both effectively mean:

`cout << args1 << '/n'; cout << args2 << '/n'; // ... cout << argsN << '/n'; `