A type-name is merely a placeholder that has to be substituted with a proper type. For example:
template T min( const T& first, const T& second); //T is a type-name, not a type
In some circumstances, an ambiguity between a type and a type-name may result:
int N;template < class T > T func(){T::A * N; // ambiguous: a multiplication statement or a pointer declaration? //_};
If T::A is a type-name, then N is a pointer; on the other hand, if T::A is a type, then “T::A * N” is an expression statement in which T::A is multiplied by a global int N.
By default, the compiler assumes that an expression like T::A is a type. The type-name keyword instructs the compiler to supersede this default interpretation and resolve the ambiguity in favor of a type-name rather than a type. In other words, the seemingly ambiguous statement above is actually resolved as a multiplication expression (the result of which is discarded). In order to declare a pointer, the type-name keyword is required:
int N;template < class T > T func(){typename T::A * N; // N is a now pointer since T::A is a type-name//_};