If you slightly change your expression, you will get a completely different story
template <class T> void foo(T::type& v);
This is no longer unique. It can declare a variable of type void , which is initialized with the bit expression AND . The whole declaration will be conceived. Of course, this is semantically all nonsense, but syntactically itβs good.
Syntactically, the appearance of one const syntax makes it unambiguous, but there is too much contextual dependency to make this work in the compiler. He must remember that he read const or any other such thing, and when he parses T::type after he needs to remember that name as a type. It would also further inflate an already complex Standard without faith.
Change the function declaration again
template <class T> void foo(const T::type);
Even the appearance of const in it does not provide unambiguous analysis. Should it be a function declaration with an unnamed parameter, or should it be a function declaration with an invalid parameter name that skips its type? The parameter name is parsed using declarator-id , which can also be a qualified name. So, here const will belong to type specifiers, and T::type will be parsed by the compiler as a parameter name, in the absence of typename . This is also complete nonsense, but syntactically valid .
In the case of base class name names, the name lookup itself claims that non-type names are ignored. Thus, you get typename inaction for free: a name that the search name returns to higher-level compiler modules either refers to the type, or the search for the name would give an error.
I wrote an entry in the FAQ about Where to put "template" and "typename" in dependent names .
Johannes Schaub - litb Dec 03 '10 at 17:31 2010-12-03 17:31
source share