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 templat
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.
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;
};
template<typename T>
typename Something<T>::Node * Something::Function1(int index) //Is the return type well written?
{
// returns the node at the specified index
}
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.