c++templatesmetaprogrammingvariadic-templatestemplate-function

Variadic template: candidate expects 1 argument, 0 provided (deduction error)


Look at this code snippet

template<class T> 
void print(T var)
{
    std::cout << var << " ";
}
 
template<class... Args> 
void Variadic(Args... args)
{
    print(args...);
}

int main()
{
     Variadic();
}

When I compile it says:

candidate: template void print(T)

candidate expects 1 argument, 0 provided

And he's right. In fact, I didn't provide any argument in the Parameter Pack.

But why, then, this code compiles?

template<class T> 
void print(T var)
{
    std::cout << var << " ";
}
 
template<class... Args> 
void Variadic(Args... args)
{
    auto x = {0, (print(args), 0)...};
}

int main()
{
     Variadic();
}

The first thing I do is to push the first 0 into the initializer_list<>

Ok, now let’s move on: the compiler sees

(print(args), 0)...

It tries to call print()… oh wait… the Parameter Pack is empty and the print() function takes 1 parameter.

Why does it evaluate to auto x = {0};, then?

Why doesn't the compiler give me the exact same error as before?


Solution

  • You misunderstand how the ... expansion operator works. In your example, when args is an empty pack, (print(args), 0)... expands to nothing, not print().

    If args was given as x it would expand to print(x), 0.

    If args was given as x, y it would expand to (print(x), 0), (print(y), 0).

    etc.

    Basically it expands all of the expression that contains args and it is applied to, not just the args bit itself.

    From the standard [temp.variadic]:

    1. A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list. The form of the pattern depends on the context in which the expansion occurs.

    ...

    1. The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a list E1, E2, ..., EN , where N is the number of elements in the pack expansion parameters. Each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith element.