Fold expression with comma operator and variadic template parameter pack

  • 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'; 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: