Search code examples
c++templatesc++20fold

Multiple arguments to binary fold expression?


I am trying to write variadic template printing using fold expressions rather than template recursion.

Currently I have

template <typename... Ts, typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os, Ts... args){
  os << '{';
  (os << ... << args);
  return os << '}';
}

For a call to many_print(1, 2);, the output is {12}.

I would like to have my output be {1, 2}.

The only close attempt I have made is

template <typename... Ts, typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os, Ts... args){
  os << '{';
  (os << ... << ((void)(os << ", "), args));
  return os << '}';
}

This uses the comma operator to print ", " for every arg. Unfortunately due to the sequencing order, the comma prints before the arg, resulting in {, 1, 2};

Are there any solutions without using template recursion?

I understand that having n-1 commas will be an issue. I would appreciate if I could even get code that outputs {1, 2, }.


Solution

  • In this case, where nothing is being computed, you can just use the comma operator for the fold itself:

    ((os << args << ", "),...)
    

    With a state variable trick, you can even omit one comma:

    int n=0;
    ((os << (n++ ? ", " : "") << args),...);