Skip the random set example, say:
using Tuple = tuple<char, int, string>;
Thus, the whole sequence with which our function will be called is:
seq<0, 1, 2>
And our package extension in the body:
(void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...};
which, if we manually expand it as the compiler will be, will become:
(void)swallow{0, (void(os << (0 == 0? "" : ", ") << std::get<0>(t)), 0), (void(os << (1 == 0? "" : ", ") << std::get<1>(t)), 0), (void(os << (2 == 0? "" : ", ") << std::get<2>(t)), 0) };
And then evaluating the branches:
(void)swallow{0, (void(os << "" << std::get<0>(t)), 0), (void(os << ", " << std::get<1>(t)), 0), (void(os << ", " << std::get<2>(t)), 0) };
In other words, we are building an integer array of 4 0 s, with the side effect of printing the contents of the tuple, separated by a comma, making sure that we do not start with an extra comma, Four expressions must be evaluated in order to ensure that the contents of the tuple will be printed in order.
The initial (void) cast is only there to avoid warning an unused variable that compilers should emit if you have all the warnings. The initial 0 in array initialization handles the case when the tuple is empty.