[Insight-developers] How to use "typename"

Brad King brad.king@kitware.com
Fri, 23 Mar 2001 17:42:03 -0500 (EST)


Hello, all:

90% of the compiler errors this week have been due to improper use of the
"typename" keyword.  I would like to try to reduce this trend.  This
message should help you understand when it should and should not be used.

There are actually two meanings of the "typename" keyword.

1.)  Easy version:

When used to declare a template parameter, it is equivalent to
"class".  This example demonstrates this case.  Both of these are
identical:

template <class T>  struct Foo {};
// is identical to
template <typename T>  struct Foo {};

2.)  Hard version:

The keyword is used to tell the compiler that the next qualified
identifier will refer to a type.  Rather than explaining the details of
why this is necessary, I will just give examples of most of the cases.

template <class T>
class MyClass
{
  // "typename" not needed because there is no "::" access.
  typedef T MyTemplateArgument;

  // "typename" needed because "T" is a template parameter of MyClass.
  typedef typename T::Foo Foo;

  // "typename" not needed because Vector<int, 3> does not depend
  // on a template parameter of MyClass.
  typedef Vector<int, 3>::Iterator VectorIterator_int;

  // "typename" needed because Vector<T, 3> DEPENDS on a template
  // parameter of MyClass.
  typedef typename Vector<T, 3>::Iterator  VectorIterator_T;

  // "typename" not needed because "Vector<float, 3>" is just a type.
  typedef Vector<float, 3>  FloatVector;
  
  // "typename" not needed because "FloatVector" does not depend
  // on a template paramaeter of MyClass.
  typedef FloatVector::Iterator  FloatVectorIterator;

  // "typename" not needed because there is no "::" access.
  typedef Vector<T, 3>  MyVector;
  
  // "typename" needed because "MyVector" depends on a template parameter
  // of MyClass.
  typedef typename MyVector::Iterator  MyVectorIterator;

  void MyMethod(); // used later in example
};

All of the above rules apply whenever you are referring to the types, not
just in a typedef.  They are even needed when referring to a type as the
template argument for another class.  However, once you have the typedef'd
name, you can just use that since the compiler knows it is a type.

For example:

template <class T>
void MyClass<T>::MyMethod()
{
  typename Vector<T, 3>::Iterator myIter;
  // is equivalent to
  typename MyVector::Iterator myIter;
  // is equivalent to
  MyVectorIterator myIter;
}

Whenever you are unsure about whether to use a typename, this email should
have an example of your situation.  If not, feel free to email the list
with the situation, and I'm sure you'll get an answer quickly.

-Brad