https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114695
--- Comment #3 from Vincent Piquet <vin.piquet at gmail dot com> --- Interesting. Now I think the issue may actually be caused by pack expansion on the call site. The issue also happens when Foo only has one base class, albeit with a different error that at least has concise types on both sides. ==== test.cpp ==== template <typename X> struct Bar { void accept(X value) { } }; template <typename...> struct Foo; template <typename... Ts> struct Foo<Bar<Ts>...> : Bar<Ts>... { template <typename T, template <typename> typename B = Bar> constexpr static B<T>* slice_by_type(B<T>* self) { return self; } template <typename... Us> void accept(Us... values) { (slice_by_type<Us>(this)->accept(values), ...); } }; int main() { Foo<Bar<float>> foo; foo.accept(3.14f); } ==== test.cpp ==== ==== GCC 13.2 ==== test.cpp: In instantiation of 'void Foo<Bar<Ts>...>::accept(Us ...) [with Us = {float}; Ts = {float}]': test.cpp:22:15: required from here test.cpp:16:27: error: no matching function for call to 'Foo<Bar<float> >::slice_by_type<float>(Foo<Bar<float> >*)' 16 | (slice_by_type<Us>(this)->accept(values), ...); | ~~~~~~~~~~~~~~~~~^~~~~~ test.cpp:10:28: note: candidate: 'template<class T, template<class> class B> static constexpr B<T>* Foo<Bar<Ts>...>::slice_by_type(B<T>*) [with B = T; Ts = {float}]' 10 | constexpr static B<T>* slice_by_type(B<T>* self) { | ^~~~~~~~~~~~~ test.cpp:10:28: note: template argument deduction/substitution failed: test.cpp:16:27: note: deduced conflicting types for parameter 'T' ('float' and 'Bar<float>') 16 | (slice_by_type<Us>(this)->accept(values), ...); | ~~~~~~~~~~~~~~~~~^~~~~~ ==== GCC 13.2 ==== This may however be simplified so much that it becomes another bug. I'm unsure.