Why?
The answer is in the body of the question. This works for classes and functions because in C there is a separate namespace for structure tags and function identifiers. If C++ aims to interoperate with C code, it must retain this behavior. One need only look at an API like the stat
function taking a struct stat
argument to realize why C++ retained the validity of such code. This working with namespaces is simply inline with C code residing in the global namespace (so ::stat
and struct ::stat
should continue to work when needed).
However, in C++ the identifiers of class tags share a "namespace" with regular identifiers. And so the validity of this "hack" is achieved with a special case in the C++ specification that simply hides classes when they would conflict.
[basic.scope.hiding]
2 A class name or enumeration name can be hidden by the name of a
variable, data member, function, or enumerator declared in the same
scope. If a class or enumeration name and a variable, data member,
function, or enumerator are declared in the same scope (in any order)
with the same name, the class or enumeration name is hidden wherever
the variable, data member, function, or enumerator name is visible.
It doesn't matter if the designers of C++ thought it was a good or bad idea. There is legacy code that should continue to be accepted as valid by C++ compilers for ease of inter-operating with certain systems.
But there is no legacy code dealing with templates that requires the same behavior. Templates are an entirely C++ construct (not related to C at all). And such, the language design doesn't have an outside constraint to add more special cases for template names too. And so it doesn't.
Suppose that having the same name is important to me. Could I somehow make this work?
No way to make it work comes to mind.