0
template <typename T, typename ... Ts>
void foo(T , Ts ... )
{
}

template <typename ... Ts, typename T>
void bar(T , Ts ... )
{
}

int main()
{
  foo<int, char>(1, 'c'); // well formed
  foo(1, 'c');

  // bar<int, char>(1, 'c'); // ill formed
  bar(1, 'c');
}

Why does explicitly specializing the template parameter function not work in the second case (bar)? It's obvious that the reason is that the parameter pack comes first in the argument-list, but still... why?

In the end of the day both cases work fine with implicit deduction. Explicitly specifying the arguments should only make it easier for the compiler.

To the person who flagged it for duplicate, I am not talking about "normal parameters" if anything like that even exists. Also I am not asking whether I can place a parameter pack before a paremeter, I am asking why I cannot explicitly specify the template arguments when pack comes first in the argument-list.

gonidelis
  • 885
  • 10
  • 32
  • You can only deduce a variadic parameter if it's the last parameter. See the linked question. – Sam Varshavchik Aug 14 '23 at 01:11
  • 1
    In both cases the variadic **argument** is the last parameter. @SamVarshavchik – gonidelis Aug 14 '23 at 01:15
  • You would need to reverse the order of your arguments. `bar` means the char is first (because of the way you wrote the template), and you're passing it second. – Tim Roberts Aug 14 '23 at 01:20
  • 1
    `bar(1, 'c');` works too. – Jarod42 Aug 14 '23 at 01:20
  • 1
    `Ts...` is "greedy", so you cannot specify `T`, `T` has to be deduced. – Jarod42 Aug 14 '23 at 01:22
  • @TimRoberts https://godbolt.org/z/o1zzx9oMG what? – gonidelis Aug 14 '23 at 01:23
  • @Jarod42 essence of the question is still there though, not allowed to explicitly specialize the pack args? (just in function param packs; and not template param packs) – gonidelis Aug 14 '23 at 01:32
  • You can explicit parameter pack (as above example `bar(1, 'c')`), but in `bar`, `Ts...` = `{char, int}`, T cannot be provided, and so you have `bar(T, char, int)` but you call it with only 2 parameters `1, 'c'`. – Jarod42 Aug 14 '23 at 01:44
  • No it's not in the second case the variadic parameter is the first template parameter. – Sam Varshavchik Aug 14 '23 at 01:46
  • 1
    @SamVarshavchik: order in `template<..>` is not important for deduction possibility, it is order in function arguments `f(Ts... non deducibles, T)`/`g(T, Ts... deducible)`. – Jarod42 Aug 14 '23 at 01:49
  • @SamVarshavchik yet `bar(1, 'c');` still deduces it. You still fail to see the lack of relevance to the linked question? – gonidelis Aug 14 '23 at 02:04

1 Answers1

0

A parameter pack is "greedy", so when you put Ts first and then explicitly specify template arguments as int, char, the pack gobbles up all the arguments specified, i.e., Ts is int, char and T has not been specified yet. T is deduced from the type of the first argument, but that means the resulting declaration of bar has parameter-type-list int, int, char, since int was deduced for T but int, char was explicitly specified for Ts. So this particular specialization of bar requires 3 arguments but you've only provided 2.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312