https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67594
--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- The primary template defines the default argument for the second parameter. The C<float,I> partial specialization is irrelevant, it isn't used. The C<float> specialization is identical to C<float, 1> because it uses the default argument, so if you write it like that then it should be obvious the code is wrong: template <typename B, int I=1> class C{}; template <int I> class C<float,I>{}; // unused template <> class C<float, 1> : public C<float, 1> {}; ^^^^^^^^^^^ ^^^^^^^^^^^ The base class matches the C<float, 1> specialization not the C<float, I> partial specialization because C<float, 1> is more specialized. So the base class is the same type, and of course a type cannot derive from itself.