C++/typename template
Expert: vijayan - 11/15/2008
Questionthe link you sent me was excellent. thank you so much :)
Could you explain the difference between the "typename" here:
template <typename T>
void List<T>::Iterator::next() {
position = position->next;
}
and here:
template <typename T>
typename List<T>::Iterator List<T>::getLast() const {
Iterator it;
it.position = NULL;
it.last = lastElement;
return it;
}
why do we have an extra typename there?
if you also have another website that explain this concept, I appreciate it.
Answerin
template < typename T >
void List<T>::Iterator::next() { position = position->next; }
the typename keyword indicates that the template parameter T is the name of a type. it could alternatively be written as
template < class T >
void List<T>::Iterator::next() { position = position->next; }
in
template <typename T>
typename List<T>::Iterator List<T>::getLast() const { ...
...
the use of typename first line is identical to the one earlier.
the use of typename in the second line is different. let me try to explain:
if we have the following function
template< typename T > void a_function( T& arg )
{
T::some_name * pointer ;
// ...
}
what T::some_name means, is not known till we know what T is.
for example, if we have a class
class contains_a_type_some_name
{
public: typedef int some_name ;
};
and we instantiate the template with T as contains_a_type_some_name,
T::some_name is an int (a type).
if we have another class contains_a_value_some_name
class contains_a_value_some_name
{
public: static int some_name ;
};
and we instantiate the template with T as contains_a_value_some_name,
T::some_name is a variable (not a type).
the meaning of
T::some_name * pointer ;
changes depending on what T is. in our example,
a. if T is contains_a_type_some_name, we are declaring iterator to be a pointer to an int.
b. if T is contains_a_value_some_name, we are multiplying an int variable with another variable called pointer.
a name like some_name in the above example is called a 'dependent name'. the meaning of the name depends on what T is. the same sequence of tokens can be parsed in two entirely different ways (depending on what T is), and there's no way to decide which is right.
to get over this problem, the parsing rule for C++ is that dependent names should be parsed as non-types (even if it leads to a syntax error). the typename keyword is used to disambiguate this; if we write
template< typename T > void a_function( T& arg )
{
typename T::some_name * pointer ;
// ...
}
we tell the compiler that the name that follows ( T::some_name ) is to be parsed as the name of a type. without it, the name are interpreted to refer to non-types.
in
template <typename T>
typename List<T>::Iterator List<T>::getLast() const { ...
typename in the second line clarifies to the compiler that the dependent name List<T>::Iterator is to be treated as the name of a type.
here is a link with a more detailed explanation:
http://pages.cs.wisc.edu/~driscoll/typename.html