Clang выводит Ts
из двух конфликтующих источников: type_list<Ts...>
и Ts&&...
. Поскольку вы звоните foo
с type_list<int>{}
, Ts
сначала выводится как {int}
. Однако, поскольку последний аргумент Ts_&&...
имеет тип пакета параметров, он перехватывает все, что может; в этом случае два последних аргумента (в то время как T_&&t
передается 5
), что выводит Ts_
как {double, int}
(и T_
как int
). Это оставляет Ts
без аргументов, поэтому выводится как {}
.
Следовательно, сообщение об ошибке Clang: Ts
выводится как {}
и {int}
((<int> vs. <>)
в сообщении об ошибке).
Обратите внимание, что GCC работает по-другому:
ошибка: слишком мало аргументов для функции 'auto foo (type_list, Ts && ..., T _ &&, Ts _ && ...) [with Ts = {int}; T_ = int; Ts_ = {double, int}] '
Он пытается сохранить Ts
как {int}
, но все равно выводит Ts_
как {double, int}
, и поэтому нет способа дать правильное количество аргументов.
Чтобы объяснить немного подробнее, рассмотрим следующее:
template <class ... Ts>
struct type_list{};
template <class ... Ts>
auto foo(type_list<Ts...>, Ts...) {
return sizeof...(Ts);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
Clang правильно вызывает это, потому что два вывода противоречивы:
примечание: шаблон кандидата игнорируется: выводит конфликтующие типы для параметра 'Ts' (<int>
против <int, double, int>
)
Проблема в том, что вы не можете поймать 2 аргумента с другим пакетом параметров, потому что он либо поймает все, если будет помещено после (как в вашем случае), либо ничего, если будет помещено до:
template <class ... Ts>
struct type_list{};
template <class... Ts, class... Ts_>
auto foo(type_list<Ts...>, Ts_..., Ts...) {
return sizeof...(Ts);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
Здесь Clang выдает то же сообщение об ошибке, поскольку Ts
по-прежнему выводится как {int}
из type_list
и {int, double, int}
путем перехвата всех оставшихся аргументов.
Я думаю, что ваш единственный выбор - как-то иметь дело с кортежами или быть более явным с помощью вызова: foo<int>(type_list<int>{}, 5, 5.0, 3)
(и вы, вероятно, можете удалить type_list
в этом случае). Таким образом, Ts
больше не выводится: вы явно делаете это {int}
.