C isn't a specialization of B. The entity between the angle brackets in C, int*
, is the value of the template parameter T
. If you're specializing A, then T
needs to be the same as the type of the parameter, which it is. If you're specializing B, then the parameter needs to be T*
, not T
.
When you change the declaration of C to
template <>
void foo<int>(int *) // C
C becomes a specialization of B but not A, by the same reasoning.
In both cases, B wins overload resolution. In the first case, there's no explicit specialization of B, so B gets called. In the second case, C, the explicit specialization of B, gets called.