Officially, what is typename for?
In some situations where you refer to a member of so called dependent type (meaning "dependent on template parameter"), the compiler cannot always unambiguously deduce the semantic meaning of the resultant construct, because it doesn't know what kind of name that is (i.e. whether it is a name of a type, a name of a data member or name of something else). In cases like that you have to disambiguate the situation by explicitly telling the compiler that the name belongs to a typename defined as a member of that dependent type.
For example
template <class T> struct S {
typename T::type i;
};
In this example the keyword typename
in necessary for the code to compile.
The same thing happens when you want to refer to a template member of dependent type, i.e. to a name that designates a template. You also have to help the compiler by using the keyword template
, although it is placed differently
template <class T> struct S {
T::template ptr<int> p;
};
In some cases it might be necessary to use both
template <class T> struct S {
typename T::template ptr<int>::type i;
};
(if I got the syntax correctly).
Of course, another role of the keyword typename
is to be used in template parameter declarations.
Following is the quote from Josuttis book:
The keyword
typename
was introduced to specify that the identifier that follows is a type. Consider the following example:template <class T> Class MyClass { typename T::SubType * ptr; ... };
Here,
typename
is used to clarify thatSubType
is a type ofclass T
. Thus,ptr
is a pointer to the typeT::SubType
. Withouttypename
,SubType
would be considered a static member. ThusT::SubType * ptr
would be a multiplication of value
SubType
of typeT
withptr
.
Consider the code
template<class T> somefunction( T * arg )
{
T::sometype x; // broken
.
.
Unfortunately, the compiler is not required to be psychic, and doesn't know whether T::sometype will end up referring to a type name or a static member of T. So, one uses typename
to tell it:
template<class T> somefunction( T * arg )
{
typename T::sometype x; // works!
.
.
Stan Lippman's BLog post suggests :-
Stroustrup reused the existing class keyword to specify a type parameter rather than introduce a new keyword that might of course break existing programs. It wasn't that a new keyword wasn't considered -- just that it wasn't considered necessary given its potential disruption. And up until the ISO-C++ standard, this was the only way to declare a type parameter.
So basically Stroustrup reused class keyword without introducing a new keyword which is changed afterwards in the standard for the following reasons
As the example given
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops …
// …
};
language grammar misinterprets T::A *aObj;
as an arithmetic expression so a new keyword is introduced called typename
typename T::A* a6;
it instructs the compiler to treat the subsequent statement as a declaration.
Since the keyword was on the payroll, heck, why not fix the confusion caused by the original decision to reuse the class keyword.
Thats why we have both
You can have a look at this post, it will definitely help you, I just extracted from it as much as I could