Replace X with int and see which of the primary templates gives a comparable signature:
template<class X> void foo(X a)
becomes
template <> void foo<int>(int)
and
template<class X> void foo(X *a)
becomes
template<> void foo<int>(int *)
Thus, it can only be a specialization of the second function. Since the function does not specialize in the first overload, it is necessary to define a second primary pattern before defining a specialization, since specialization cannot specialize the first primary pattern.
If the template argument is not explicitly specified in the specialization, the corresponding primary template is found using the normal argument output rules in accordance with clause 14.8.2.6 [temp.deduct.decl]:
In the declaration, the id-id of which refers to the specialization of the function template, the template argument is output to determine the specialization to which the declaration relates. In particular, this is done for explicit authorities (14.7.2), explicit specializations (14.7.3) and some declarations of friends (14.5.4).
This argument output takes into account the partial order of the primary patterns, i.e. finds the second primary pattern. I did not fall into the trap of reading the paragraph leading to the limerick, but the warning is valid: I think you will get in trouble if you change the order of the second primary template and specialization! Beware of the mention of self-immolation mentioned.
source share