When should I use the keyword "typename" when using templates

I've been working lately on a small project, and I couldn't figure out something..

I've been given a .h file that was containing a class, using a typename template. Inside that class there was a private class.

template <typename T>
class Something
{
public:
        Something();
        ~Something();

        Node* Function1(int index);
        int Index(const T& id);


private:
        class Node()
        {
                public:
                T id;

                //Imagine the rest for the Node


        };      
};

The problem occured when I wanted to define the functions of the class "Something"

Here's how I was doing it (in a .inl file)

template<typename T>
Node* Something::Function1(int index) //Is the return type well written?
{
        // returns the node at the specified index
}

template<typename T>
int Something::Index(const T& id) //Is the parameter type well specified?
{
        // returns the index of the node with the specified id
}

So the bugging part was in the definitions part... Do I have to tell the compiler that the return type (in this case Node*) uses the typename template (like this: typename Node*) ? And what about the parameter ? typename const Node& ?

So basically, when do I have to specify wether the function/parameter uses a template?

Thanks for your time.


For Function1, you need to tell the compiler what Node is -- in this case, it's a nested type inside Something<T>. Because it's dependent on T (it's a dependent name), you need to tell the compiler it's a type, so you must write it as typename Something<T>::Node. The issue is that there might be some T for which Something<T>::Node isn't actually a type (i.e. if you partially specialize Something<T>).

For Index, what you have is fine -- const T& is just a reference to a const T, and the compiler knows what T is.


The simple rule: You need to use the typename keyword every time you name a type using the Class::Type syntax, if the Class part depends on a template parameter. (The Class part might be a template parameter, or it might be a typedef in your class template, etc.)

Edit: There's also some confusion about nested class scoping rules. This is mostly independent of the typename issue, so here's a non-template example.

class Outer {
public:
  class Inner {
  };
  Inner* func(Inner* obj);
};

Outer::Inner* func(Inner* obj)
{
}

The full name of Inner is Outer::Inner. But you can also use the shorter name Inner anywhere from the scope of class Outer, including all of the declaration of func. At the definition of func, the return type is NOT in the scope of Outer, so the full name is necessary. But after the (, the function parameters ARE in the scope of Outer, so the short name is okay.

Combining this with the template-ness of the original example, since the equivalent of Outer is Something<T>, you need the typename keyword to say Something<T>::Node.


template<typename T>
typename Something<T>::Node * Something::Function1(int index) //Is the return type well written?
{
        // returns the node at the specified index
}

typename and class are equivalent in template type parameter list:

template <class T> class C;

is the same as

template <typename T> class C;

Where the typename is required is when referring to dependent names:

template <typename T> struct A {
    typedef typename T::some_type container;
};