How to loop through a list of variadic arguments

186 Views Asked by At

When I tried to iterate over variadic arguments via the following function

I don't understand '{(Print(Param),0)... } 'where 0 is used

#include<iostream>
using namespace std;


template<typename T>
void Print(T& arg)
{
    cout << arg << endl;

}

template<typename ...ParamTypes>
void Func(ParamTypes &...Param)
{
    int arr[] = { (Print(Param),0)... }; 

}
int main()
{
    int num = 10;

    Func(num,num,num);

    return 0;
}

It gives me an error when I don't add 0

2

There are 2 best solutions below

4
On

As Print if a (template) function returning void, some hack is needed to manipulate it in an expression. Here:

int arr[] = { (Print(Param),0)... }; 

the comma operator (,) is used to make sure the side-effect of Print is manifested and yet something is returned: the zero int. Indeed, you cannot construct an array of voids.

As a reminder, the comma operator evaluates its left-hand operand, discards its result, and finally returns its right-hand operand.

It is in my humble opinion a bad hack. A more clear/explicit could be constructed:

struct side_effect_t
{
    side_effect_t(...) {}
};

template<typename T>
side_effect_t Print(T& arg)
{
    std::cout << arg << '\n';
    return {};
}

template<typename ...ParamTypes>
void Func(ParamTypes &...Param)
{
    side_effect_t{ Print(Param)... };
}

demo on godbold

1
On

This a C++14 workaround for C++17 fold expressions where you can just write:

template<typename ...ParamTypes>
void Func(ParamTypes &...Param)
{
    (Print(Param),... ); 
}

Print(Param),0 calls Print, throws away the result (if any) and evaluates to 0.

int arr[] = { (Print(Param),0)... }; 

Creates an array of bunch of zeros, but for C++14 this was one of the few places where variadic parameter packs could be expanded.