I know that the comma operator is probably the easiest way to do that, but for completeness here's something I came up with, mainly because I wanted to show off my little generalisation of iomanip. The standard library iomanips are functions. There's an <<
overload that takes a function pointer. I extended that for arbitrary callable objects that take and return streams by reference.
template <class Stream, class Func>
auto operator << (Stream& s, Func f) ->
std::enable_if_t<std::is_same_v<decltype(f(s)), Stream&>, Stream&>
{
return f(s);
}
With this little tool in our toolbox, it's easy to write a fold expression that does absolutely anything we want.
template<typename ...Args>
void output_args(Args&&... args)
{
(std::cout << ... << [&](auto& x)->auto&{return x << args << '\n';});
}
This technique can be used in scenarios where we need to capture the value of the fold expression, rather than its side effects. The comma operator is less useful in such contexts.