Я испортил это;теперь все должно быть в порядке, но заслуга @UncleBens ниже, который правильно понял (и должен получить «принять»).
Без B
в вашей третьей версии, у вас есть двачастичные специализации, которые одинаково специфичны при создании экземпляра S<S<X,Y,Z>, T1, T2, T3>
:
- Первый PS:
A = S<X,Y,Z>
, B = T1
, C... = T2, T3
. - Второй PS без
B
:A... = X,Y,Z
, C... = T1, T2, T3
. - Второй PS с
B
: A... = X,Y,Z
, B = T1
, C... = T2, T3
.
Это не устанавливает сопоставимые элементы вПорядок частичной специализации!
Обратите внимание, что вы можете сказать template <typename ...> struct S;
и template <typename A, typename ...B> struct S<A, B...>;
, а второй более конкретен, чем первый, потому что у него больше невариантных параметров.
Но нас другой стороны, без B
, когда вы говорите S<S<X,Y,Z>,T1,T2,T3>
, первый аргумент лучше соответствует второму PS, но остальные аргументы лучше соответствуют первому PS.Однако при наличии B
второй PS более конкретен.
Сравните это с частичной специализацией, которую является на самом деле более конкретным:
template <typename ...A, typename B, typename ...C>
struct S<B, std::tuple<C...>, std::tuple<C...>> { /* ... */ };
Теперь понятно, соответствует ли данный экземпляр специализации или только общему виду.Специализация имеет фиксированное количество параметров (3), поэтому она выигрывает у другой специализации с переменным числом аргументов.