Ваша ошибка - Foo<Others>*... o
аргумент. Распаковка этого аргумента для пакета шаблонов A, B, C, D, E
даст вам столько o
аргументов: Foo<A>, Foo<B>, Foo<C>, ...
.
На мой взгляд, было бы проще, если бы вы просто объявили свои аргументы как Other
и пусть рекурсия завершится неудачно, если в дальнейшем они не будут соответствовать ни одному экземпляру Foo
:
template <typename T1, typename T2, typename... Others> size_t getSize(Foo<T1,T2> *f, Others... *o) { ... };
Здесь каждый тип Others
в пакете будет выведен на тип, который вы передаете. Если вы вызываете getSize
рекурсивно с уменьшенным количеством аргументов, все они в конечном итоге будут сопоставлены с аргументом Foo<T1,T2>
:
return f->size()
+ getSize(std::forward<Others>(o)...); // the first argument in the pack will
// be Foo<T3,T4> type
// or the compilation will fail
Вы также можете добавить черту типа, чтобы выполнить проверку напрямую:
template <class T> struct IsFoo : std::false_type {};
template <class T, class U> struct IsFoo<Foo<T,U>> : std::true_type {};
template </* ... */>
std::enable_if_t<std::conjunction<IsFoo<Others>::value...>::value, size_t> getSize(/* ... */)