This answer explains the behaviour of the following program:
template<typename A, typename B = int > struct FirstWins { static constexpr int i = 1; }; template<typename A> struct FirstWins<A, float/* anything different from int */ > { static constexpr int i = 2; }; template<typename A, typename B = int > struct SecondWins { static constexpr int i = 1; }; template<typename A> struct SecondWins<A, int > { static constexpr int i = 2; }; int main() { typedef void Whatever_t; cout << FirstWins < Whatever_t >::i << endl; // prints 1 cout << SecondWins< Whatever_t >::i << endl; // prints 2 return 0; } However, I cannot find an actual reference describing explicitly this behaviour and thus confirming the answer.
I could not find on cppreference.com a sentence confirming that explicit template arguments are preferred over default ones.
I suspect that this is not really the rule. The rule is that whenever there is a partial template specialization matching the template arguments, that specialization is always chosen over the instantiation of the primary template. Is this correct? (in this case, the docs somehow explain this rule, but again not explicitly).
FirstWins<X>resolves asFirstWins<X, int>. The actual selection of the definition ofFirstWins<X, int>happens after the "substitution" ofBforint.SecondWins<X, int>. In that case,SecondWins<X, int>is preferred overSecondWins<X, =int>.SecondWins<A, B=int>is no different thanSecondWins<A, B>for template selection, and so the specializationSecondsWins<A, int>is preferred over the non-specialized one. The default template argument has no impact here for the resolution.FirstWins. There it is the mismatch between the default parameterB=intand the explicit onefloatthat leads to the selection of the first.Bdefaulting to anything that is notfloatdoes make the difference.