dimanche 28 novembre 2021

Function Template Type Deduction Rules

I have:

template<typename ...Ts, typename U, typename=void>
void valid(Ts..., U){}

int main() {
    valid(1.0, 1, 2, 3);
}

clang complains:

note: candidate function [with Ts = <>, U = double, $2 = void] not viable: requires 1 argument, but 4 were provided
void valid(Ts..., U){}
     ^

And gcc complains:

<source>:2:6: note:   template argument deduction/substitution failed:
<source>:5:10: note:   candidate expects 1 argument, 4 provided
    5 |     valid(1.0, 1, 2, 3);
      |     ~~~~~^~~~~~~~~~~~~~

According to cling, it seems like the compiler deduces that Tn is an empty pack (i.e. <>). Why is that? I thought given the argument list (1.0, 1, 2, 3), U would be deduced to int and Tn... would be double, int, int. What are the rules here for the type deduction?

If I changes the caller to:

valid<double, int, int>(1.0, 1, 2, 3);

It works. However, if I change it to:

valid<double, int, int, int>(1.0, 1, 2, 3);

It fails:

<source>:2:6: note:   template argument deduction/substitution failed:
<source>:5:33: note:   candidate expects 5 arguments, 4 provided
    5 |     valid<double, int, int, int>(1.0, 1, 2, 3);
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~

What rules are used here to determine what types I can specify in the type parameter list?

Thanks.

Aucun commentaire:

Enregistrer un commentaire