Search code examples
c++variadic-templatestemplate-argument-deduction

Explicitly-specified template parameter packs


Let's say, I have the following piece of code:

#include <iostream>

template <size_t... Is> struct E {};

template <typename... Ts, size_t... Is>
void func (E<Is...>, Ts...) {std::cout << __PRETTY_FUNCTION__ << std::endl;}

int main()
{
    func(E<1,2,3>{}, 1, 'a');
}

It works perfectly fine and produces

void func(E<Is ...>, Ts ...) [with Ts = {int, char}; long unsigned int ...Is = {1, 2, 3}]

However, if I replace func call with func<int, char, 1, 2, 3>(E<1,2,3>{}, 1, 'a');, it will cause the compilation error, i.e.,

template argument deduction/substitution failed

Why compiler forbids the explicit specification of multiple parameter packs?


Solution

  • This follows from the rules for template argument deduction.

    When you explicitly specify the template parameters for func, the compiler will match it to the first parameter pack greedily. The compiler does not figure out that once you start putting ints in the parameters, it should start substituting for Is....

    Instead, it will continue substituting for Ts..., and you'll get an error message along the lines of:

    expected a type, but got 1
    

    for the 3rd explicitly specified parameter.

    You can see this if you specify only the Ts..., like this:

    func<int, char>(E<1,2,3>{}, 1, 'a');
    

    which compiles just fine.