Search code examples
c++c++17variadic-templatesfoldfold-expression

C++17 Variadic Template Folding


I don't understand why this doesn't work. Could someone who understands templates and variadic expression folding explain what is going on and give a solution that does work?

#include <iostream>
#include <string>

template <typename... Args>
void print(Args... args)
{
    std::string sep = " ";
    std::string end = "\n";
    (std::cout << ... << sep << args) << end;
}

int main()
{
    print(1, 2, 3);
}

It should print out each of the args with a space in between and a newline at the end. It works if you remove the sep << but then there is no space between each argument when it is printed.


Solution

  • The grammar for binary fold-expressions must be one of:

    (pack op ... op init)
    (init op ... op pack)
    

    What you have is (std::cout << ... << sep << args), which doesn't fit either form. You need something like (cout << ... << pack), which is why removing sep works.

    Instead, you can either fold over a comma:

    ((std::cout << sep << args), ...);
    

    or use recursion:

    template <class A, class... Args>
    void print(A arg, Args... args) {
        std::cout << arg;
        if constexpr (sizeof...(Args) > 0) {
            std::cout << sep;
            print(args...);
        }
    }