Вы можете свести ваше дело к следующему:
f<int>(1);
Что может быть истолковано как вызов:
R f<R, T, Ts...>(T, Ts...) // with `R = int`, `T=int` and `Ts = <>`
или звонок на:
T f<T, Ts>(T, Ts...) // with `T = int` and `Ts = <>`
Обратите внимание, что более специализированное обоснование частичного упорядочения шаблонов применяется к типам аргументов, и здесь они оба одинаковы, поэтому 2 перегрузки считаются одинаково действительными для вашего вызова, что приводит к неоднозначности.
Чтобы решить, что вам нужно что-то, чтобы дисквалифицировать одну из двух перегрузок. Кажется, вы хотите извлечь первого члена вашего пакета, соответствующего запрошенному типу ... Для этого вы можете использовать дизайн на основе SFINAE:
template< typename R, typename T, typename... Ts >
std::enable_if_t< std::is_same< R, T >::value, R > f( T a, Ts... )
{
return a;
}
template< typename R, typename T, typename... Ts >
std::enable_if_t< ! std::is_same< R, T >::value, R > f( T, Ts... args )
{
return f< R >( args... );
}