The template <>
notation introduced a full specialization of a template: that is, the general version of the template is not used when the deduced template parameters are those of the full specialization. However, any deviation would still use the general template:
foo(17); // uses your general template
foo("hello"); // also uses your general template! T is deduced as char const*
char world[] = "world";
foo(world) // uses your specialization
In principle, this is exactly who overloading would work! Obviously, for class templates there is no overloading and you'd need to specialize them. However, even for function templates specialization is reasonable: when the template arguments are explicitly specified:
foo<char*>(world); // calls the specialization
If you use overloading instead, the overload wouldn't be used:
template <typename T>
void bar(T) { /*...*/ }
void bar(char*) { /*...*/ }
bar(world); // calls the bar(char*) overload
bar<char*>(world); // calls the template
With respect to your two alternatives: the second alternative isn't legal C++. The second definition looks a bit like a specialization but you need to introduce a specialization using template <>
.